0

I am currently working on a project which modify some images and save it again. However, I have noticed that sometimes the resulted image is drastically different than the original one in terms of file size in bytes. Even if the modifications were very small such as changing colour on a single pixel. So I decided to do this experiment where I load an image and save it again immediately to new file without any changes (using C# Bitmap class). I was expecting to get the same size in both files but unfortunately the actual sizes were not identical. Here is my code:

String originalImagePath = "image.png";
String savedImagePath = "image2.png";
Bitmap image = new Bitmap(originalImagePath);
image.Save(savedImagePath);

Assert.AreEqual(new FileInfo(originalImagePath).Length, new FileInfo(savedImagePath).Length);

Assert.AreEqual failed. 
Expected:<218144>.Actual:<344264>.

Should both files have the same sizes? If no, then what I am missing here?
And how can I generate identical file?
Here is the image that I am using: PNG Image

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
Mashaal
  • 3
  • 1
  • 1
  • 3
  • 1
    You are saving a PNG file into BMP format. BMP format is the largest one out of JPG, PNG & GIF. That is the reason the file size is greater. – Gagan Jaura Oct 16 '15 at 12:36
  • Check out this question: http://stackoverflow.com/questions/30858883/why-bitmap-save-changes-images-size – Shogun Oct 16 '15 at 12:36
  • Thanks @Shogun, it is interesting to know that many other factors can determine the file size. Does this also apply to PNG? or is it just for JPEG? – Mashaal Oct 16 '15 at 13:00
  • 1
    The PNG file format is a compressed format, the compression algorithm does not necessarily produce consistent sizes. There is a trade-off between time and size. But considering the file size increase, the most likely mishap here is that the file got saved back with a bigger pixel format. The .NET codec doesn't like the indexed formats, for a good reason, and converts them to 32bppARgb. Not otherwise something you can tweak. – Hans Passant Oct 16 '15 at 14:18
  • @HansPassant The conversion of indexed images to 32bpp [is a weird bug specifically and only occurring when loading the palette transparency chunk from a PNG image](https://stackoverflow.com/a/43137699/395685), which definitely doesn't hold any kind of logic behind it, since the .Net framework _can write_ pngs with such alpha palettes. Also, that image is certainly not indexed. The .Net png compression is simply not good. – Nyerguds Jan 26 '18 at 14:14

1 Answers1

4

There really isn't anything strange about this. You're saving a PNG file, which only really defines how the file is supposed to be decoded, but not how to do the actual compression. Different applications can produce vastly different file sizes, just by the virtue of having a different compression tables. There's usually also some tweaking you can do (e.g. limit the palette of the file, or picking between coding/decoding speed and file size).

This is seen very clearly by using a tool such as PNG Gauntlet, which takes a PNG file on input, and produces a pixel-by-pixel identical image, just with a vastly reduced file size (usually around 30% less space, but I've seen results up to 70% smaller).

And of course, in the end, even if everything else is equal, a tiny change in the bitmap can result in a significant file increase anyway. Maybe you've broken some pattern that was especially easy to compress. Maybe you can no longer fit in a 8-bit palette. Maybe you've added transparent channels. There's plenty more.

Luaan
  • 62,244
  • 7
  • 97
  • 116