I ran oxipng on a palette PNG and the tool told me it saved 8.50%. When I wrote the same result in my notes as a share of the original file, it was 1.6 points. Both numbers are correct, and they answer different questions. This post is about keeping them apart. The files are 12 PNGs from Wikimedia Commons (CC licenses): three screenshots, three icons, three illustrations and three photos. One run each on an Apple M4, pngquant 3.0.3, oxipng 10.2.1, sizes in exact bytes.
The tool prints a percentage of its own input
The icon was 40,369 bytes. pngquant at quality 65–80 brought it to 7,600, then oxipng brought it to 6,954. Here is the full oxipng output:
$ cp Q.png Q_ox.png; oxipng -o 4 --strip safe Q_ox.png
Files processed: 1/1
Input size: 7.42 KiB (7600 bytes)
Output size: 6.79 KiB (6954 bytes)
Total saved: 646 bytes (8.50%)
The 8.50% is 646 divided by 7,600, the quantized file that oxipng received. Divided by the original 40,369 it is 1.6 points. zopflipng does the same thing with different words: its "Percentage of original" line below is 6,923 divided by 7,600, so "original" there means its input as well.
$ zopflipng -y --filters=01234mepb Q.png Q_zop.png
Optimizing Q.png
Input size: 7600 (7K)
Result size: 6923 (6K). Percentage of original: 91.092%
Result is smaller
Which base makes the gain look bigger
Quoting the gain relative to the quantized file always looks larger, because that file is already small. On all 12 files together the originals add up to 4,454,411 bytes, pngquant leaves 1,411,877, and oxipng after it leaves 1,283,130. That is 2.9 points of the original, or 9.1% of what pngquant left. Neither is a lie, but "9.1% smaller" reads like a different kind of result than "2.9 points".
The per-class numbers show a second problem, which is that the base can change the ranking.
| Class | Extra from oxipng, points of original | Extra from oxipng, % of quantized file |
|---|---|---|
| Photos | 4.0 | 11.8% |
| Icons | 3.1 | 15.3% |
| Screenshots | 1.9 | 6.0% |
| Illustrations | 1.6 | 6.4% |
By points, photos lead and icons come second. By percent of the quantized file, icons lead. Screenshots and illustrations also swap places. If I had only kept the second column I would have written that icons benefit most, and someone who only saw the first column would write photos. Three files per class is too few to say which is right, and I did not look into why the classes differ, so I treat the table as a description of these 12 files and nothing more.
Why I settled on points of the original
My rule now is to put the base next to every number. For a pipeline I use the original file as the base, since that is what a reader ships or downloads, and I say "points" so nobody reads 1.6 as a relative gain. The quantized-file figure only goes in when the point is how much one step adds on top of the previous one, and I label it that way.
Timing needs the same care. oxipng added roughly 0.8 to 1.6 seconds per class of three files on this machine, and zopflipng added 3.5 to 19.5 seconds for 0.0 to 0.5 extra points. The zopflipng comparison only holds for the flags above, and I did not try higher iteration counts.
The same check on someone else's palette PNGs
To get palette PNGs I had not made myself, I fed the same 12 files to the batch compressor on ImgIng (https://imging.ai/) in a desktop browser, output forced to PNG. Seven results were larger than their inputs and one file was left untouched. The other four were smaller palette PNGs, and those are the ones I ran oxipng on.
On the icon, ImgIng gave 9,346 bytes and oxipng gave 6,301. That is 32.6% of the ImgIng output and 7.5 points of the 40,369-byte original. The biggest relative gain was a 120,393-byte star icon: 43,216 down to 23,571, which is 45.5% of the output and 16.3 points of the original. This is a batch run on four files, not the single-image page, so it shows that such output can still shrink and says nothing about how much a typical file would.
Top comments (0)