APNG support

cédric (dev) said on 09/19/2018

APNG is a hack from Mozilla of the PNG specifications — supported by Chrome, Safari and Firefox atm — which let users to transform PNG files to have animations. the beginning of those files are very closed to PNG, so even an old pingo should be able to handle this (accidentally), since the first frame is still IDAT, like PNG

in older versions however, you could expect the animation removal, since the APNG chunks were not supported. from pingo 0.94, it should be able to detect and handle them in a more efficient way automatically, whatever the option: it preserves what is necessary to keep the animation

APNG optimization

regarding image data, APNG is formed with an IDAT chunk (from PNG), and fdAT which is basically IDAT + seq. if you plan to optimize those files entirely, you should have to process all those chunks — that takes time, because you could process each frame like an individual image

pingo's implementation

this is actually work in progress. the current stuff is very primitive. always backup your file!

pingo could process APNG files losslessly for Web or with the same additionnal lossy from PNG: paletted encoding, the lossy filter or the color quantization. here is how it works:

pingo 0.98.19
options type application what it does
what transformation
-noapng skip - skip all APNG files
-sN web lossless iDAT only web lossless optimization
-apng=0 web lossless iDAT/fdAT (partial) web lossless optimization
-apng=1 web lossless iDAT/fdAT (full) web lossless optimization
-apng=2 lossy (soft) iDAT/fdAT (full) transform image data for a filter
-apng=3 lossy (average) iDAT/fdAT (full) reduce the number of colors (preserve alpha)
-apng=4 lossy (aggressive) iDAT/fdAT (full) image data to paletted (256 colors max)
-auto (or none) lossy (adaptive) auto select automatically lossy type / quality
how much the transformation is done
-apngquality 1 - 100 - set the quality factor

from apng=1 to apng=4, you could use the -grayscale or -notrans options to do transformations on the image data. note that this can not be done with apng=0

-sN — web lossless

pingo 0.98.19 — PNG profiles
apng-dirty-transparency.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
apngopt 1.4 32-bit -z0 1.13s 541.81 KB 427.84 KB
pingo 0.98.19 32-bit -s0 0.26s 541.81 KB 417.26 KB

it seems that some tools which let the user to create APNG are nice enought to provide some optimizations tricks, so they do not provide really bad files. the deflate and reductions from pingo could optimize further, but not that much — so to preserve speed, the default v.lossless (-sN) is only processing the IDAT and is ignoring fdAT atm

-apng=1 — web lossless

you could go further to optimize losslessly for Web your APNG files. if you use -apng=1, it will process IDAT and fdAT — i.e the whole data stream — which require more time to process while saving more bytes. note that the -sN profiles for APNG are less aggressive than regular PNG

pingo 0.98.19 — the filtering
apng-dirty-transparency.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
PngOptimizer 2.5.1 (f2701cb) 32-bit - 1.98s 541.81 KB 541.81 KB — none
apngopt 1.4 32-bit -z0 1.13s 541.81 KB 427.84 KB
-z1 3.26s 541.81 KB 408.55 KB
-z2 30.55s 541.81 KB 405.48 KB
pingo 0.98.19 32-bit -apng=1 -s4 1.97s 541.81 KB 405.32 KB
pingo 0.98.19 32-bit -apng=1 -s8 2.54s 541.81 KB 401.69 KB

it benefits from the filtering and palette sorting reductions but in a bit different way: bytes could be filtered by up to 3 strategies, i.e fast, medium and brute. each one could be used on IDAT and/or fdAT according to the level. that speeds up the process about 20% while providing better results than one strategy with more iterations

pingo 0.98.19 — the palette sorting
apng-zephyr.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
PngOptimizer 2.5.1 (f2701cb) 32-bit - 4.70s 617.97 KB 617.97 KB — none
apngopt 1.4 32-bit -z0 0.82s 617.97 KB 666.00 KBbigger
-z1 3.00s 617.97 KB 616.87 KB
-z2 14.70s 617.97 KB 615.12 KB
pingo 0.98.19 32-bit -apng=1 -s0 1.63s 617.97 KB 548.87 KB
pingo 0.98.19 32-bit -apng=1 -s4 2.39s 617.97 KB 536.79 KB

regarding the palette sorting, pingo is even more lazy: it does try only the minimal possible trial in low modes (-s0 to -s3) while one more is done in higher modes. note that this optimization is also enabled when you convert the APNG to paletted — i.e. using -apng=4

-apng=2 — lossy filtering

pingo is able to apply the lossy filtering on APNG files. this can be useful especially if paletted encoding is too aggressive regarding the perceptual quality. it transforms RGB values to match what the filter could expect, using by default a soft dithering

pingo 0.98.19 — the lossy filtering
apng-alpha.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
pingo 0.98.19 32-bit -apng=2 -s0 1.04s 314.18 KB 229.22 KB
pingo 0.98.19 32-bit -apng=2 -apngquality=50 -s0 0.88s 314.18 KB 145.92 KB
pingo 0.98.19 32-bit -apng=2 -apngquality=10 -s0 0.87s 314.18 KB 102.10 KB

-apng=3 — color quantization

pingo could do color quantization on RGB data, while preserving alpha values. it could try to preserve better perceptual quality than paletted encoding, but usually compresses worse. it could be useful sometimes on small images which use some alpha values

pingo 0.98.19 — the color quantization
apng-tweet.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
pingo 0.98.19 32-bit -apng=3 -s0 1.63s 371.76 KB 209.31 KB

-apng=4 — paletted

pingo could transform your image data to paletted with 256 colors or less. this is usually the most aggressive move regarding image quality but also the one which offer the best savings. it could be tried on most of image but is especially efficient on flat and simple graphics

pingo 0.98.19 — the paletted encoding
apng-purple-pony.png — G1820 @ 2.7 Ghz - 2 Go RAM - Windows 7 32-bit
tool version binary options time in out
pingo 0.98.19 32-bit -apng=4 -s0 1.48s 306.50 KB 104.97 KB
pingo 0.98.19 32-bit -apng=4 -apngquality=20 -s9 -nodithering 3.20s 306.50 KB 63.38 KB

trials (demo)

elephant — (+) 50% savings tomato — (+) 50% savings fly — (+) 90% savings
gray — (+) 65% savings bird — (+) 45% savings pony — (+) 79% savings

cédric (dev) said on 09/24/2018

by doing more tests with 0.98.23, i find out the lossless slow so i started something else in 0.98.24: -apng=0, which does a new APNG optimization way that could be hopefully faster than what is already implemented. instead of processing the whole data with lot of reductions, it targets minimal effective reductions to preserve speed

-apng=0 — web lossless

it targets a web lossless optimization and preserves more speed by avoiding some reductions during the process. however, according to my very basic test on it, you could get a far better efficiency especially on low levels. on this specific sample, it is more than 3x faster while offering more compression

pingo 0.98.24 — APNG web lossless -s0
apng-dirty-transparency.png — FX-4100 @ 3.6 Ghz - 8 Go RAM - Windows 7 64-bit
tool version binary options time in out
pingo 0.98.24 64-bit -s0 0.27s 541.81 KB 417.26 KB
pingo 0.98.24 64-bit -apng=1 -s0 1.41s 541.81 KB 412.44 KB
pingo 0.98.24 64-bit -apng=0 -s0 0.45s 541.81 KB 412.25 KB

you could also try to combine with an higher -sN to beat the reduction done in -apng=1 by speed and size: even if the reduction could be worse with -apng=0, the higher level in compression could makes the difference while the process could be faster

pingo 0.98.24 — APNG web lossless -s0
apng-tweet.png — FX-4100 @ 3.6 Ghz - 8 Go RAM - Windows 7 64-bit
tool version binary options time in out
pingo 0.98.24 64-bit -apng=1 -s0 (better reduction, lower compression) 1.99s 371.76 KB 362.11 KB
pingo 0.98.24 64-bit -apng=0 -s3 (lower reduction, better compression) 1.70s 371.76 KB 357.63 KB

however, that does not mean it is always true: if you go for compression (higher -sN), most of the time -apng=1 could offer better results

pingo 0.98.24 — APNG web lossless -s9
apng-dirty-transparency.png — FX-4100 @ 3.6 Ghz - 8 Go RAM - Windows 7 64-bit
tool version binary options time in out
pingo 0.98.24 64-bit -apng=1 -s9 3.38s 541.81 KB 401.46 KB
pingo 0.98.24 64-bit -apng=0 -s9 2.05s 541.81 KB 405.22 KB
pingo 0.98.24 — APNG web lossless -s9
apng-tweet.png — FX-4100 @ 3.6 Ghz - 8 Go RAM - Windows 7 64-bit
tool version binary options time in out
pingo 0.98.24 64-bit -apng=1 -s9 4.08s 371.76 KB 351.74 KB
pingo 0.98.24 64-bit -apng=0 -s9 3.20s 371.76 KB 355.77 KB

room for improvement

even if i did only very basic test regarding the current APNG implementation, it is obvious that pingo could be better on this in many ways:

  • speed up with multiprocessing which is always enabled by default for PNG, unlike APNG files which are procedeed one by one atm. note that if you optimize PNG and APNG in a same command, PNG could be still optimized with multiprocessing
  • speed up -apng=1, which could adopt the same implementation than -apng=0
  • increase compression of APNG which are < 8 bpp; atm, they are just passed throught the web-lossless -sN for PNG. it could not be able to reduce the bitdepth

comment this