Wednesday, November 5, 2008

PNG palette with variable alpha: small and great for webbrowser

I am working on the MapTiler/GDAL2Tiles open-source project for user-friendly static tile publishing of maps in the style of Google Maps. This project started as my Google Summer of Code project for OSGEO and results are published in coming GDAL 1.6.

Recently I was testing several optimization of PNG for minimizing the tile size with preserving reasonable image quality as this is crucial for my application. Such optimization speeds up the download and also saves a lot of space on the hard disk. There is plenty of tools available for optimizing the size of PNG: advpng, pngrewrite, pngcrush, pngquant, scolorq, pngnq... I wanted to choose one of them for postprocessing of tiles (or probably later on integrate such optimization directly into GDAL).

The best optimization of the PNG filesize is always based on reduction of the amount of used colors: when you switch from RGB(A) model to palette. What I didn't know before is that PNG supports palette with variable alpha. It means that part of the definition of every color in the palette is also its transparency. It is possible to use functionality usually available only with separate alpha channels but with palette!

After switching to PNG with palette you need just half or even less of the space for your image raster data. Of course conversion from RGBA to palette is lossy operation for images with a lot of colors... but with well chosen algorithm for quantization it can be almost not recognizable for humans. Especially for small tiles like in MapTiler case.

The PNG with the alpha palette is correctly displayed in all latest web-browsers like Firefox 2+, Safari, Explorer 7+ and also in Google Earth.
But wait that is not all! Internet Explorer 5.5 & 6 displays such PNG files with (limited) transparency without HTML hacking! That is just great because it allows you to easily display map overlays in the old browsers by viewers like OpenLayers or Google Maps and still be able to dynamically change opacity for map overlay containing transparent parts!

Well, if it is so great, how to produce such file? There is very nice open-source application for converting standard RGBA PNGs into this PNG8 with alpha palette:

PNGNQ: http://pngnq.sourceforge.net/ (by Stuart Coyle and Greg Roelofs)

It is using The NeuQuant Neural-Net image quantization algorithm (by Anthony Dekker) which was documented in this PDF article. With slightly modified version of this algorithm it converts standard PNG24 with RGBA into PNG8 with alpha palette. It is quite fast.
The result PNG file has usually half of the size of the original.
If you are crazy about the produced png size you can try to compress the file with pngcruch postprocessing step. Sometimes it decrese the size of the result even a bit more.

The documentation at the PNGNQ project page recommends to run:

pngnq -n 256 image.png && pngcrush image-nq8.png smallimage.png


This PNGNQ tool is excellent for post-processing of PNG tiles generated from MapTiler/GDAL2Tiles...

And it seems that the source code of the utility itself as well as of dependencies like NeuQuant algorithm is compatible with BSD license so they have a chance to find a way into GDAL or other open-source tools which are processing maps...

1 comment: