1

This is the code I'm using to convert the TIFF to PNG.

var image = Image.FromFile(@"Test.tiff");

var encoders = ImageCodecInfo.GetImageEncoders();
var imageCodecInfo = encoders.FirstOrDefault(encoder => encoder.MimeType == "image/tiff");

if (imageCodecInfo == null)
{
   return;
}

var imageEncoderParams = new EncoderParameters(1);
imageEncoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
image.Save(@"Test.png", imageCodecInfo, imageEncoderParams);

The TIFF file size is 46.8 MB (49,161,628 bytes) the PNG that is made using this code is 46.8 MB (49,081,870 bytes) but if I use MS paint the PNG file size is 6.69 MB (7,021,160 bytes).

So what do I change in the code to get the same compress I get by using MS Paint?

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
NewCoder
  • 21
  • 3
  • Possible duplicate of [C#: Seeking PNG Compression algorithm/library](http://stackoverflow.com/questions/4418454/c-seeking-png-compression-algorithm-library) – Mick May 01 '17 at 07:59

2 Answers2

1

Without a good Minimal, Complete, and Verifiable code example, it's impossible to know for sure. But…

The code you posted appears to be getting a TIFF encoder, not a PNG encoder. Just because you name the file with a ".png" extension does not mean that you will get a PNG file. It's the encoder that determines the actual file format.

And it makes perfect sense that if you use the TIFF encoder, you're going to get a file that's exactly the same size as the TIFF file you started with.

Instead, try:

var imageCodecInfo = encoders.FirstOrDefault(encoder => encoder.MimeType == "image/png");

Note that this may or may not get you exactly the same compression used by Paint. PNG has a wide variety of compression "knobs" to adjust the exact way it compresses, and you don't get access to most of those through the .NET API. Paint may or may not be using the same values as your .NET program. But you should at least get a similar level of compression.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • That looks like the real reason. The quality setting that could control a ratio/speed tradeoff would never create such a huge difference, even if it were implemented. Some links seem to suggest that the quality may have changed from .Net 2 to 4 to 4.5, btw.. – TaW May 01 '17 at 08:00
  • 1
    @TaW: my thinking as well. Unfortunately, it appears that neither GDI+, nor the WPF API (which uses WIC for bitmap encoding) provide a way to control any encoder settings for PNG formats. :( But even the default algorithm will compress an image to some significant degree, which isn't happening in the OP's case. – Peter Duniho May 01 '17 at 08:02
  • By changing "image/tiff" to "image/png" helped the file size is now 29.5 MB (31,014,574 bytes). So there isn't any really any way in .NET to control PNG compression? I'm still new to C# so please bear with me. – NewCoder May 01 '17 at 08:59
  • @New: _"there isn't any really any way in .NET to control PNG compression?"_ -- not easily, no. You can write your own PNG wrapper (e.g. to call WIC or libpng), or use a third-party PNG library. As far as the results you got, keep in mind that the TIFF may also already be compressed, using one of the TIFF-specific compression formats. So the 33% reduction in size you got might be about as good as you're going to get with a lossless codec (you say you got much better results from Paint, but we don't know for sure what format you saved in). Can't say for sure w/out the actual TIFF file itself. – Peter Duniho May 01 '17 at 09:24
  • I really didn't want to use any third-party solutions but it looks like that's what i'm going to have to do. As for paint all I did was open the TIFF file and save it as a PNG. – NewCoder May 01 '17 at 09:54
  • I still don't see why you need a 3rd party optimzation. Simply save as png but correctly! What results do you get with this: `image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);` ?? Also note: Sometimes a special image will get special results.. – TaW May 01 '17 at 14:11
  • I am getting the same results using `image.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);` as when I changed "image/tiff" to "image/png" the PNG file size is 29.5 MB (31,014,574 bytes). – NewCoder May 01 '17 at 16:02
0

OK, after a lot of trial and error I came up with this.

                var image = Image.FromFile(@"Test.tiff");
                Bitmap bm = null;
                PictureBox pb = null;

                pb = new PictureBox();
                pb.Size = new Size(image.Width, image.Height);
                pb.Image = image;
                bm = new Bitmap(image.Width, image.Height);
                ImageCodecInfo png = GetEncoder(ImageFormat.Png);
                EncoderParameters imageEncoderParams = new EncoderParameters(1);
                imageEncoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                pb.DrawToBitmap(bm, pb.ClientRectangle);
                bm.Save(@"Test.png", png, encodePars);
                pb.Dispose();

And add this to my code.

            private ImageCodecInfo GetEncoder(ImageFormat format)
            {
               ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
               foreach (ImageCodecInfo codec in codecs)
               if (codec.FormatID == format.Guid)
               return codec;
               return null;
             }

By loading the TIFF in a PictureBox then saving it as a PNG the output PNG file size is 7.64 MB (8,012,608 bytes). Witch is a little larger then Paint But that is fine.

NewCoder
  • 21
  • 3