OVERHEAD

System update

BYTE WARS

Log entry (14/10/2023)

Since my arrival on Planet Zopfli, I have been beholden to a tepidly persuasive contract: Marginally improved output in exchange for lengthy processing times, each yield requiring up to four samples of differing origins. Thankfully, this dull endeavour was disrupted by a notification which painted itself on my terminal:

OxiPNG v9.0.0 firmware now available. Restart mining subsystem to apply updates.

Important update

OxiPNG v9.0.0 has been released, which naturally means some of the results from before have changed because of new optimisations and updated dependencies, here’s hoping on some improvements!

Please eliminate the variants.

Please eliminate the variants.

COME ON! COME ON! COME-

Data analysis

Typical case

Ah, screw it, you know the drill by now.

The interesting stuff

Results for the ‘series-deciphering_hugo.png’ image, with the best-to-worst encoding order being: OxiPNG-ZF or Oxi-ZF-Quant, OxiPNG or Oxi-Quant, CWebP, PNGQuant, then Original.

Filename:		'series-deciphering_hugo.png'
Original Filesize:	3819 bytes
PNGQuant Filesize:	1990 bytes
OxiPNG Filesize:	1885 bytes
OxiPNG-ZF Filesize:	1849 bytes
Oxi-Quant Filesize:	1885 bytes
Oxi-ZF-Quant Filesize:	1849 bytes
CWebP Filesize:		1918 bytes
Smallest encoding:	1849 bytes, OxiPNG-ZF

Okay, we saved one byte for the Zopfli variants, same story though.

Results for the ’tag-css.png’ image, with the best-to-worst encoding order being: CWebP, OxiPNG or Oxi-Quant or OxiPNG-ZF or Oxi-ZF-Quant, PNGQuant, then Original.

Filename:		'tag-css.png'
Original Filesize:	4780 bytes
PNGQuant Filesize:	2474 bytes
OxiPNG Filesize:	2261 bytes
OxiPNG-ZF Filesize:	2261 bytes
Oxi-Quant Filesize:	2261 bytes
Oxi-ZF-Quant Filesize:	2261 bytes
CWebP Filesize:		2054 bytes
Smallest encoding:	2054 bytes, CWebP

With the OxiPNG update, a lot of the size differences between the variants have been flattened out, however, like in this case, the results can be worse compared to the previous release (e.g. “OxiPNG-ZF” output size from the previous release: 2256 bytes, which is five bytes smaller).

Of course, “CWebP” was more effective here anyways, so the actual smallest encoding didn’t increase at all, I just thought this point was noteworthy.

Results for the ‘Invert.png’ image, with the best-to-worst encoding order being: CWebP, Oxi-ZF-Quant, OxiPNG-ZF, Oxi-Quant, OxiPNG, Original, then PNGQuant.

Filename:		'Invert.png'
Original Filesize:	1542935 bytes
PNGQuant Filesize:	1586364 bytes
OxiPNG Filesize:	1506472 bytes
OxiPNG-ZF Filesize:	1501598 bytes
Oxi-Quant Filesize:	1504355 bytes
Oxi-ZF-Quant Filesize:	1501474 bytes
CWebP Filesize:		1356018 bytes
Smallest encoding:	1356018 bytes, CWebP

And as you can see by the ‘Invert.png’ results, the PNGQuant combos are, annoyingly, still effective. Sure, “CWebP” absolutely destroys the OxiPNG variants here, but if we encounter a ‘series-deciphering_hugo.png’-esque result, we’ll need to try all the OxiPNG variants regardless to ensure the smallest encoding is found.

Strangely, this specific pre-release build of OxiPNG achieved an even smaller output at 1500130 bytes (Oxi-ZF-Quant variant).

Why? Well now, I think I have an answer.

Indexed colours

The pre-release build and the “PNGQuant” variants share a difficult problem which is (most likely) the cause of the output size variance: Colour palette optimisation.

Each index in an indexed colour palette consists of a single byte, however, not every byte is equally compressible, 00000010 is a lot simpler than 01110011 (and that’s not even considering when the bytes are chained together), therefore, the frequency of each colour and thus its index drastically affects the image data’s compressibility.

Unfortunately, palette optimisation isn’t trivial to solve nor implement, although algorithms focused on this problem do exist as found by Kornel (the creator of pngquant and Gifski).

https://www.researchgate.net/publication/51371279_A_Survey_on_Palette_Reordering_Methods_for_Improving_the_Compression_of_Color-Indexed_Images

https://scholar.google.com/scholar?q=palette+reordering PDFs

kornelski

Heuristics

In hopes of reducing the amount of processing time needed per image, I’m proposing a new heuristic for avoiding the OxiPNG variants in most cases:

  • Typically, the normal OxiPNG output is more than 10% larger than the “CWebP” output.
  • And usually, the OxiPNG variants are less than 10% smaller than the normal OxiPNG output.
  • Therefore, if the OxiPNG output isn’t within 110% of the “CWebP” output, you can skip running the OxiPNG variants as it’s unlikely any of them would find a smaller image encoding.

Obviously, these percentages are based solely on my image set, which is only about twenty images and it’s biased towards my own pixel art, so to create a more generic heuristic, I’ll need to expand my dataset. Until then…