Skip to content

How is an image compressed into a png? How to choose among the available programs?

yumeyao edited this page Nov 12, 2013 · 2 revisions

PNG metadata & datastream overview

Like almost every other data format, PNG has a metadata(or, i.e. header) and a real datastream representing the image(pixels).

There are 2 most important factors that impact on the datastream, dimensions(width & height) and colorspace(bit depth & color type).

How is the data represented

Once the dimensions and color-representation are given, we could build a unique basic uncompressed datastream(Assuming in palette colorspace, the palette is given too).

The datastream consults height scanlines, for each scanline it contains width pixels, and each pixel is finally represented by the specific colorspace(for example, 8-bit RGB).

So how is it compressed

Many says PNG's data is compressed in the same way zip is. This is only partly true.

Before sending the unique basic uncompressed datastream to a deflater(zip-compatible compressor, for example zlib), PNG allows for applying filters on the datastream to make it able to be compressed more efficiently.

The filter option is scanline-wide, i.e. you can choose a different filter for each row of pixels. There are totally 5 types of filters[0-4]. After applying the filters, the datastream is what really sent to the deflater.

So here if we apply a specific filter type globally, the datastream is still unique. But if we apply it adaptively, the datastream is not unique if the adaptive algorithm varies.

So in short, what really impact on the final out put size?

Bitmap -> PNG-compatible unfiltered raster -> filtered data -> zipped data

  1. Bitmap -> PNG-compatible unfiltered raster
    If the destination colorspace is not palette, the unfiltered raster is always byte-identical.
    Otherwise the colors in different palettes may be arranged by different order, therefore the unfiltered raster is not byte-identical(different byte codes from multiple tryouts may refer to a same color in different palettes).
    So if the destination colorspace is palette. We need to do some tryouts to find 'good' palette(s).

  2. PNG-compatible unfiltered raster -> filtered data
    By using different filters, The compressibility of filtered data varies.
    We need to do tryouts to find 'good' filter(s).

  3. filtered data -> zipped data
    Definitely we should use a good deflater. zlib is obviously NOT a good choice.

So what about current available programs?

Advpng from advcomp always applies filter 0 globally (that is, no filter, or say, no data change). So it's absolutely a bad compressor. You can always use zopflipng --filters=0 to do the same thing as advpng -z -4 do.

When destination colorspace is palette, pngout's palette is not fixed.

When you use pngcrush/optipng/pngout/zopflipng with 0-4 specified to the corresponding option, the selected filter is global applied. pngcrush/optipng/pngout 5 == zopflipng entropy(not very sure. or maybe some == zopflipng minimum sum)

So pngcrush & optipng is USELESS if you have pngout/zopflipng. No matter what arguments you provide to them, the zlib compressor always fails to be the best. And all what they provide besides zlib are color reduction & filters, which are a subset of pngout/zopflipng features.

That's why this script only uses pngout & zopflipng to take the tryouts of png optimization.

Reference

PNG spec @ http://www.w3.org/TR/PNG/