-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PNG optimizer strategies from TruePNG #71
Comments
Oxipng already uses some of these techniques, but it looks like there are improvements to be gained here. I'll probably turn this into a meta issue and make sub-issues for each potential improvement, once I have time to go through the full list in detail. |
Thanks. At https://blog.codinghorror.com/zopfli-optimization-literally-free-bandwidth/ you can find an image that almost not optimized with oxipng (- 28 bytes), while TruePNG does much better (- 7016 bytes). # Download image.
$ wget https://blog.codinghorror.com/content/images/2016/01/PBF274-Adam_2-0.png
# Compress original PNG with oxipng max setting (zlib):
$ oxipng -o 6 --zm 1-9 --strip all --out PBF274-Adam_2-0.oxipng_o6_zm1_9.png PBF274-Adam_2-0.png
Processing: PBF274-Adam_2-0.png
800x1412 pixels, PNG format
4x8 bits/pixel, RGBA
IDAT size = 607025 bytes
File size = 607110 bytes
Trying: 1944 combinations
IDAT size = 607025 bytes (0 bytes decrease)
file size = 607082 bytes (28 bytes = 0.00% decrease)
Output: PBF274-Adam_2-0.oxipng_o6_zm1_9.png
# Compress original PNG with oxipng max setting (zopfli):
$ oxipng -o 6 --zopfli --strip all --out PBF274-Adam_2-0.oxipng_o6_zopfli.png PBF274-Adam_2-0.png
Processing: PBF274-Adam_2-0.png
800x1412 pixels, PNG format
4x8 bits/pixel, RGBA
IDAT size = 607025 bytes
File size = 607110 bytes
Trying: 6 combinations
Found better combination:
zc = 0 zm = 0 zs = 0 f = 0 581799 bytes
IDAT size = 581799 bytes (25226 bytes decrease)
file size = 581856 bytes (25254 bytes = 4.16% decrease)
Output: PBF274-Adam_2-0.oxipng_o6_zopfli.png
# Compress original PNG with TruePNG max setting:
$ wine TruePNG.exe PBF274-Adam_2-0.png /o max /out PBF274-Adam_2-0.truepng_max.png
TruePNG 0.6.2.2 : PNG Optimizer
by x128 (2010-2016)
[email protected]
Input file: PBF274-Adam_2-0.png | 607110 bytes
Image: 800x1412 pixels | 8 bits/sample | RGB & Alpha
Delta filter: None
Chunks: gAMA
Output format: 8 bits/sample | RGB & Alpha
Chunks: gAMA
try...
IDAT=600021 file=600094 complete=100%
extra...
best:
zc:9 zm:8 zs:0 fs-: f:0 IDAT=600021 file=600094
# Compress original PNG with zopflipng.
$ zopflipng --iterations=10 PBF274-Adam_2-0.png PBF274-Adam_2-0.zopflipng_it10.png
Optimizing PBF274-Adam_2-0.png
Input size: 607110 (592K)
Result size: 581721 (568K). Percentage of original: 95.818%
Result is smaller
# Compress oxipng optimized file (with zlib) with zopflipng.
$ zopflipng --iterations=10 PBF274-Adam_2-0.oxipng_o6_zm1_9.png PBF274-Adam_2-0.oxipng_o6_zm1_9.zopflipng_it10.png
Optimizing PBF274-Adam_2-0.oxipng_o6_zm1_9.png
Input size: 607082 (592K)
Result size: 581721 (568K). Percentage of original: 95.822%
Result is smaller
# Compress oxipng optimized file (with zopfli) with zopflipng.
$ zopflipng --iterations=10 PBF274-Adam_2-0.oxipng_o6_zopfli.png PBF274-Adam_2-0.oxipng_o6_zopfli.zopflipng_it10.png
Optimizing PBF274-Adam_2-0.oxipng_o6_zopfli.png
Input size: 581856 (568K)
Result size: 581721 (568K). Percentage of original: 99.977%
Result is smaller
# Compress TruePNG optimized PNG with zopflipng.
$ zopflipng --iterations=10 PBF274-Adam_2-0.truepng_max.png PBF274-Adam_2-0.truepng_max.zopflipng_it10.png
Optimizing PBF274-Adam_2-0.truepng_max.png
Input size: 600094 (586K)
Result size: 576829 (563K). Percentage of original: 96.123%
Result is smaller
# PNG filesizes:
$ stat --format '%n'$'\t''%s' PBF274-Adam_2-0.*png
PBF274-Adam_2-0.oxipng_o6_zm1_9.png 607082
PBF274-Adam_2-0.oxipng_o6_zm1_9.zopflipng_it10.png 581721
PBF274-Adam_2-0.oxipng_o6_zopfli.png 581856
PBF274-Adam_2-0.oxipng_o6_zopfli.zopflipng_it10.png 581721
PBF274-Adam_2-0.png 607110
PBF274-Adam_2-0.truepng_max.png 600094
PBF274-Adam_2-0.truepng_max.zopflipng_it10.png 576829
PBF274-Adam_2-0.zopflipng_it10.png 581721 |
I might not have used TruePNG correctly, but on my input it's barely better than what I could get with oxipng... yet whatever compressor.io is doing, it's able to do huge reductions by comparison with image quality that looks the same.
Compress.io Lossy setting, 29.2KiB Would be nice if there are any easy wins there for oxipng to offer a lossy output option too :) |
It looks like compressor.io uses pngquant behind the scenes, which uses quantization to reduce the number of colors needed to store a PNG image. It looks like this is represented in #76, but I must have checked off the wrong item in the list on this issue, because it's not implemented in oxipng yet. |
1 note: Be careful that you don't replicate TruePNG's faults (e.g., it can destroy certain 2-bit grayscale PNGs in a weird almost-interlaced fashion). @javiergutierrezchamorro I've filed an extensive bug report re: this for FO. |
#502 completed №3 (#73) above. @guls, @shssoichiro: Could that be checked off in the top post? |
In the mean time I switched from TruePNG to It seems like The following seems to generate much better images than in the past:
# Original image ==> reduced with pngquant ==> pngquant image recompressed with zopflipng CLI tool.
-rw-r--r-- 1 ghuls domain users 18044 Dez 1 2021 test.original.png
-rw-r--r-- 1 ghuls domain users 7761 Dez 1 2021 test.pngquant.png
-rw-r--r-- 1 ghuls domain users 6963 Dez 1 2021 test.pngquant_with_zopflipng.png
# Original image ==> reduced with oxipng (with -Z option) ==> oxipng image recompressed with zopflipng CLI tool.
-rw-r--r-- 1 ghuls domain users 18044 Dez 1 2021 test.original.png
-rw-r--r-- 1 ghuls domain users 7065 Mai 8 16:32 /tmp/test.oxipng.png
-rw-r--r-- 1 ghuls domain users 6972 Mai 8 18:44 /tmp/test_oxipng.zopflipng.png
|
Be aware that there's a vast amount of work in OxiPNG since v8.0 release (& more still in-process) so, if you're not building from sources/PRs, you've still not witnessed OxiPNG's current best. |
When I tested it, yesterday, I build the latest git version |
@ghuls Are all your PNGs ≤256 colors? If not, |
@TPS Yes they are. They are very simple PNG images made with weblogo: https://weblogo.threeplusone.com/examples.html#splice Maybe you didn't see it well, oxipng ( When comparing the pngquant and oxipng PNG files, both have 162 colors pallet and the colors are exactly the same according to imagemagick $ identify test.pngquant.png
test.pngquant.png PNG 399x199 399x199+0+0 8-bit sRGB 162c 7761B 0.000u 0:00.000
$ identify /tmp/test.oxipng.png
/tmp/test.oxipng.png PNG 399x199 399x199+0+0 8-bit sRGB 162c 7065B 0.000u 0:00.000
$ compare -metric PSNR test.pngquant.png /tmp/test.oxipng.png /tmp/diff.png
inf |
IIUC, #414 → #495 &/or #169 (comment) would solve this, also. |
@ghuls I suspect the difference may be due to palette order - oxipng only sorts by luminance while zopfli (or pngquant) may try different methods which happen to better here. Try using |
I use the original zopfli. At first I had problems generating the same small file with pngquant + zopflipng (smallest I got was only 6972) as the one I made 2 years ago. Then I remembered that I enabled extra rounds of compresssion: When running
|
Right, we can see here that zopflipng gives a different palette order than oxipng by itself, which likely explains the size difference. This is probably coincidental rather zopflipng just being "better" - afaik it doesn't actually have any explicit palette sorting algorithms. Chances are oxipng will be better on average (aside from the |
@andrews05 Here is the image: |
Thanks. Sadly though, the new palette sorting did not improve this image. |
TruePNG is a very good PNG optimizer, unfortunately it only runs on Windows (and under wine).
Some of the strategies is uses are described:
Meta issues:
The text was updated successfully, but these errors were encountered: