Sunday, August 18, 2013

A Comparison of PNG Compression Methods

You may remember my past post about which image format you should be using.  The summary was use PNG for computer generated graphics.  I briefly touched on the fact that PNG allows you to use 24 bit or 8 bit colors.  It is, however, much more complicated than that.


Intro

There are three color modes available in PNG.  The mode with the fullest color space is RGB 24 bit.  The second mode is indexed.  It allows you to use 8 bits or less for up to 256 colors.  Additionally, it allows you to choose the palette.  The last mode is grayscale.  As the name implies it's black and white, but allows a gradient of grays.  By comparison, a 1 bit indexed mode would only allow full black or full white, no grays.

Generally, switching to indexed offers a pretty big savings in file size.  However, you can often get even greater savings by going to less than 8 bit color.  Doing so will generally require generating a custom palette to take full advantage of the reduced color space.  If the file is black and white, it can sometimes be worth it to switch to grayscale or to 1 bit indexed.

There really is no simple way to know which will be best, besides trial and error.  Doing this for one file is a bit annoying, but doing it for many files is pretty unreasonable.  As such, many PNG compressors have popped up to help automate this process.

It turns out that the compression process is not so clean cut, and thus many of the various programs perform differently on various files.  I decided to look into if my current program was a good choice.  I found a few old comparisons, but not any from the last few years.  I decided to just download a bunch of programs and try them out.

I didn't download too many, preferring those that either had recent development, or were spoken highly of somewhere.


Programs Tested

So without further ado, here are the candidates:

TinyPNG - Has been my go to.  It's the only web based option here.  It's quite fast and has a great interface.

pngquant v1.8.3 - Some research showed that pngquant was the library being used at TinyPNG.  I figured if I could have the same compression as TinyPNG as a command line tool, that would be ideal.

pngcrush v1.7.9 - This is the standard PNG compression utility.

optipng v0.7.4 - Another standard utility, based on pngcrush.

pngout 20130221 - Based largely on the recommendation of this 6 year old Jeff Atwood post.  It is still being developed though.

Before I get into the results I should note the command line switches used.  In all cases its none.  Some of the utilities are geared more towards automatic use than others.  There is no doubt you could achieve much better results if you were willing to experiment with the options.  However, that wasn't the use case I was testing here.  I was concerned with processing dozens or more files quickly and easily.

If you want to see the images used I uploaded them to imgur here.  Unfortunately, imgur is no dummy, they compressed the files themselves.  They also resized the largest ones and converted some to jpg when that made sense.  If you want all the files, both the original and the results, I uploaded them as a zip to mediafire.

Results

Filesizes in KB:
NameOriginaloptipngpngcrushpngoutquantpngtinypngt2osmallest
a.png885765879769335329328328
b.png5.743.225.052.773.363.273.272.77
c.png27272723272025822725258725832582
e.png84.632.484.637.233.232.432.432.4
f.png22.919.720.916.419.618.116.616.4
g.png44.217.623.631.315.014.013.513.5
i.png717550616529189181181181
m.png30.729.129.126.829.427.927.126.8
n.png48.047.948.042.526.625.624.024.0
o.png22.222.222.219.122.222.219.119.1
p.png104410191019973288281281281
r.png545188243174188174174174
s.png476311316352156147146146
t.png11.611.611.611.612.612.011.611.6
w.png79.458.759.973.739.836.536.136.1
x.png60.760.760.760.261.958.658.658.6
y.png90.078.990.070.848.045.142.242.2
z.png104.6104.6104.6102.152.650.850.050.0
sum70006043635458734246404540274025


Ratio to the best compression method:
Originaloptipngpngcrushpngoutquantpngtinypngt2o
a.png270%233%268%234%102%100%100%
b.png207%116%182%100%121%118%118%
c.png106%105%105%100%106%100%100%
e.png261%100%261%115%102%100%100%
f.png140%120%127%100%120%111%101%
g.png326%130%174%231%111%103%100%
i.png397%304%340%292%105%100%100%
m.png114%108%108%100%109%104%101%
n.png200%200%200%177%111%107%100%
o.png116%116%116%100%117%117%100%
p.png372%363%363%347%102%100%100%
r.png314%108%140%100%108%100%100%
s.png326%213%217%241%107%101%100%
t.png100%100%100%100%108%103%100%
w.png220%162%166%204%110%101%100%
x.png104%104%104%103%106%100%100%
y.png213%187%213%168%114%107%100%
z.png209%209%209%204%105%102%100%
sum174%150%158%146%105%100%100%
geo201.0%152.0%174.1%152.2%109.0%103.9%101.1%

In the first table sum for all columns is just the sum of the column.  In the second table sum is the ratio of sum to the smallest sum.  In other words, a sum ratio of 100% should indicate a perfect score, but it's skewed by the large file sizes.  The geometric mean solves this for the normalized ratios.  Or does itYeah, probably.


Analysis

I think the take away here is that TinyPNG is the winner.  That being said, you'll note there were three cases where it did significantly worse than pngout.  Images b and o were both black and white, and pngout turned b into grayscale, but both left o as indexed.  What's more, e was grayscaled by pngout for worse size than the indexed tinyPNG version.  Pretty clear evidence that grayscale vs indexed  isn't clear cut.

quantpng is consistently a few percent higher than TinyPNG, lending credence to the idea that TinyPNG is using quantpng, but then also doing something else to squeeze a bit of filesize out.  On the other hand, quantpng actually made a few files worse, so maybe there is some overhead on its end.

The alert reader will have noticed there is a seventh algorithm listed which wasn't defined above.  t2o is a response to the fact that either TinyPNG or pngout was the optimal algorithm.  It is the TinyPNG files ran through pngout.

While it almost always does better than TinyPNG or pngout alone, you'll note the one case where it failed to return to the level pngout had achieved on the raw file.

I suppose my strategy will be to continue to use TinyPNG, and if I really need to minimize a file, run it through pngout independently, and compare the results.

No comments:

Post a Comment