0

I need to convert a tiff file that is in black and white colors to png using .net. but i am unable to reduce color depth to 8 bit per pixel. it always output the file in 24 bit per pixel. Is there any way i can do this in .net? or any open source Managed library to do so?

code i am using.

public bool convertTiffToJpg(string sourceFile, string targetFile)
        {

            bool response = false;

            try
            {

                // Get individual Images from the original image
                Image sourceImage = Bitmap.FromFile(sourceFile);

                var total = sourceImage.GetFrameCount(FrameDimension.Page);
                var pageNumbers = Enumerable.Range(0, total).ToArray();
                Image[] sourceImages = new Image[pageNumbers.Length];
                for (int i = 0; i < pageNumbers.Length; i++)
                {
                    sourceImage.SelectActiveFrame(FrameDimension.Page, pageNumbers[i]);
                    float width = sourceImage.Width;
                    float height = sourceImage.Height;
                    ResizeImage(1000, sourceImage.Height, ref width, ref height);

                    using (var returnImage = new Bitmap(sourceImage, (int)width, (int)height))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            returnImage.Save(ms, ImageFormat.Jpeg);
                            sourceImages[i] = Image.FromStream(ms);
                        }
                    }
                }

                // Merge individual Images into one Image
                var totalHeight = sourceImages.FirstOrDefault().Height * total;
                var totalWidth = sourceImages.FirstOrDefault().Width;
                using (var finalImage = new Bitmap(totalWidth, totalHeight))
                {
                    using (var g = Graphics.FromImage(finalImage))
                    {
                        // All other pages
                        for (int i = 0; i < pageNumbers.Length; i++)
                        {
                            g.DrawImage(sourceImages[i], new Point(0, sourceImages[i].Height * i));
                        }
                    }
                        ImageCodecInfo Codec = ImageCodecInfo.GetImageEncoders().Where(codec => codec.FormatID.Equals(ImageFormat.Png.Guid)).FirstOrDefault();

                        finalImage.Save(targetFile, Codec, GetCodedParams(50));
                }

                response = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return response;
        }

private EncoderParameters GetCodedParams(int? quality)
        {
            var imageQuality = quality ?? 80;
            EncoderParameter ratio = new EncoderParameter(Encoder.Quality, imageQuality);
            EncoderParameter light = new EncoderParameter(Encoder.ColorDepth, 8L);
            EncoderParameters codecParameters = new EncoderParameters(2);
            codecParameters.Param[0] = ratio;
            codecParameters.Param[1] = light;
            return codecParameters;
        }

but still i am unable to get png of 8bit depth.

Regards.

Shoaib Shaikh
  • 4,565
  • 1
  • 27
  • 35

1 Answers1

0

This is what i come up with. i used Image Quantization to reduce color depth.

http://msdn.microsoft.com/en-us/library/aa479306.aspx this is there i got the quantizer

 public bool convertTiffToPng(string sourceFile, string targetFile)
        {

            bool response = false;

            try
            {

                // Get individual Images from the original image
                Image sourceImage = Bitmap.FromFile(sourceFile);

                var total = sourceImage.GetFrameCount(FrameDimension.Page);
                var pageNumbers = Enumerable.Range(0, total).ToArray();
                Image[] sourceImages = new Image[pageNumbers.Length];
                for (int i = 0; i < pageNumbers.Length; i++)
                {
                    sourceImage.SelectActiveFrame(FrameDimension.Page, pageNumbers[i]);
                    float width = sourceImage.Width;
                    float height = sourceImage.Height;
                    ResizeImage(1024, sourceImage.Height, ref width, ref height);

                    using (var returnImage = new Bitmap(sourceImage, (int)width, (int)height))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            returnImage.Save(ms, ImageFormat.Jpeg);
                            sourceImages[i] = Image.FromStream(ms);
                        }
                    }
                }
                 var p = new System.Collections.ArrayList();
                    p.Add(Color.Black);
                    p.Add(Color.Gray);
                    p.Add(Color.LightGray);
                    p.Add(Color.DarkGray);
                    p.Add(Color.White);
                    PaletteQuantizer quantizer = new PaletteQuantizer(p);
                    //OctreeQuantizer quantizer = new OctreeQuantizer(2,2);

                // Merge individual Images into one Image
                var totalHeight = sourceImages.FirstOrDefault().Height * total;
                var totalWidth = sourceImages.FirstOrDefault().Width;
                using (var finalImage = new Bitmap(totalWidth, totalHeight))
                {

                    using (var g = Graphics.FromImage(finalImage))
                    {
                        g.InterpolationMode = InterpolationMode.Low;
                        g.PixelOffsetMode = PixelOffsetMode.HighSpeed;

                        // All other pages
                        for (int i = 0; i < pageNumbers.Length; i++)
                        {
                            g.DrawImage(sourceImages[i], new Point(0, sourceImages[i].Height * i));
                        }
                    }

                    //finalImage.MakeTransparent(Color.White);
                    using (var toout = quantizer.Quantize(finalImage))
                    {
                        ImageCodecInfo Codec = ImageCodecInfo.GetImageEncoders().Where(codec => codec.FormatID.Equals(ImageFormat.Png.Guid)).FirstOrDefault();
                        toout.Save(targetFile, Codec, GetCodedParams(null));
                    }

                }

                response = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            return response;
        }
Shoaib Shaikh
  • 4,565
  • 1
  • 27
  • 35
  • 1
    Why do you convert from Tiff (I would assume a Group 4 Tiff since it is black and white) to a JPEG (which is a lossy compression) before writing all the pages to your PNG. Also I don't know what your ResizeImage does, but from a cursory glance of the code it seems like you are assuming all pages in the Tiff are the same size. I don't know the domain you are using this in, but Tiff's can have different size pages (go to a recorder of deeds office and grab some tiffs, many times they have legal size pages, 8.5 x 11, and huge property plats in the same file) – pstrjds Apr 13 '12 at 13:04
  • yes tiffs are in black and white having same page size for all frames, all i need a png format just because i want them to be displayed in silverlight application(which don't support tiff) first i tried to convert tiff in jpeg and as you said its a horrible option because jpegs are designed to use more colors and its compression fits best for colored images. then i am left with png option. as i know tiff don't need to have 24bit color depth i tried to reduce their color depth to 8bit and used palette quantization to reduce colors to only black and white. – Shoaib Shaikh Apr 13 '12 at 15:24
  • i also want to know if i can make white color to transparent of png as most of the documents use white background. and how much it will affect the png filesize? – Shoaib Shaikh Apr 13 '12 at 15:27