Yet another fascinating look into the world of small PNG files (an earlier article looks at scanline filtering). This is a cautionary tale about saving PNGs using OS X Preview.
Consider the following image:
It’s produced by using OS X Preview to copy a section from this image:
It’s 1334 bytes long! It’s only 8×8 pixels in size, so at 3 bytes per pixel (1 each for R, G, and B) the actual raster data should be 192 bytes. That’ll get compressed, and then there’ll be some overhead. But even so, 1334 bytes seems profligate.
So it turns out that the image has an iCCP chunk. A colour profile. Not only is that a 439 byte overhead, it’s not justified. The image is not produced using a colour managed tool chain. It’s copied from a section of an image on the web. Hmm, it turns out that the source image has a gAMA chunk (intended gamma); I wonder if that makes Preview add a colour profile? Anyway, leaving that colour profile aside…
The image is colormapped with a palette (PNG color type 3). That’s probably quite sensible for an 8×8 image. But it’s a sin to make the palette have 256 entries. That’s 768 bytes; and the PLTE chunk doesn’t get compressed. An 8×8 image can clearly have a maximum number of colours of only 64, so clearly the palette only needs 64 entries at most (in a PNG, the palette need only have as many entries as are used; this is a good feature).
It turns out that the image only uses 10 colours! So the palette need only have 10 entries. Moreover, that means a bit depth of 4 could be used instead of 8. That may or may not be an improvement. The uncompressed IDAT chunk will be smaller with a bit depth of 4, but a bit depth of 8 may compress better (also, it may filter better).
It turns out that these problems are because the source image was a PNG. Creating a BMP file of the same image and then getting OS X Preview to save that as a PNG creates a PNG file with no iCCP chunk and bit depth 4. The PLTE chunk still has 16 entries rather than 10; that’s only wasting 18 bytes in this case, but if we had a low colour image that required a bit depth of 8, 17 colours say, then it could waste 717 bytes (239 entries), and that is exactly what it does for a 17 colour image.
Argh! It turns out Preview only creates a paletted PNG from a BMP when the BMP is paletted. If I go back to my original image (the large PNG), extract the 8×8 tile using Preview and save that as a BMP it creates a truecolor BMP; and saving that BMP as a PNG creates a truecolor PNG (that is, one without a PLTE chunk).
When I saved a PNG from the original PNG the palette that gets used is the 256 entry palette from the original image. Well, except that some of the entries have been tweaked by a bit or so (I suspect it has been “colour corrected” and then saved). That strikes me as rather unintuitive, and only occasionally useful. So occasional that I would expect it either to be an option when saving or only available in a pro tool, like Photoshop.
It seems that when I’m using Preview to crop images, I may as well save in any format I like and then use Netpbm’s pnmtopng to create a PNG. pnmtopng does a good job for this image size, but sometimes it could do better.