Image corruption with invalid transparency
Advanced PNG optimization program
Status: Beta
Brought to you by:
cosmin
Tested with current v0.7.8 Win32 binary. Using: optipng.exe -q -i0 -zc1 -zm8 -zs3 -f0 -force "%~1" (but issue will occur with most conversions / typical parameters).
When getting transparency chunk via libpng, validity is not tested before converting color type. Here, the RGB transparency index does not appear in the palette.
This can lead to image corruption. See attached.
I have highlighted the defective pixel (that becomes full transparent), to red for clarity - attached.
I started to debug this before, but lost my notes...
I observe the issue with non-paletted images (RGB/A), that have a
tRNSchunk that specifies an RGB value not present in an image. May affect grayscale images too (G/A) ?When the image is optimised as indexed, the transparency is wrongly applied to the palette index.
I think the issue is in the use of libpng
png_get_tRNS…?“…For non-paletted images, the function retrieves the single color value which is treated as fully transparent. If the transparency information is valid, i.e. PNG_INFO_tRNS bit is set for info_ptr >valid: * trans shall be set to the transparency values for a paletted image. Values for the data shall be in range [0,255], ranging from fully transparent to fully opaque, respectively. * num_trans shall be set to the number of transparency values * trans_values shall be set to the single color value specified for non-paletted images. …”
Last edit: Andrew 2024-01-26
Andrew, I tried to reproduce the corruption that you're seeing, but I couldn't. I tried it both on Windows and Linux, and both with the embedded libpng and with the system libpng. If you could please take a look at my command line and let me know what I am missing.
The resulting file
out.pngis identical toactions.png.And then I tried the same but with
actions-broken.png:The resulting file
out.pngis not identical toactions-broken.png, but the image content is the same. I can even see the red pixel, which is the difference in transparency that you mentioned, but that is NOT the output of optipng, from what I'm seeing:My conclusion, from my own experiments, is that
actions-broken.pngmust have come from some other place, because I could not breakactions.pngby using optipng in the way that you reported.Please ignore my previous message. I must have done something in which I did not manipulate the test images correctly, before running my tests; but after a full reset of my test environment, now I confirm that you bug report is 100% legit.
Example 2
To aid debugging, this test case is perhaps more obvious?
See attached 'toolbar.png'. The image is RGB with a
tRNSchunk defining RGB(0,0,1) as transparent. Critically, this colour doesn't exist in the image, so there should be no transparency. When viewing, the image has a bright green background. Details are also confirmed with TweakPNG.Image is optimized on Win32 with Batch command line
optipng.exe -v -f0 -force "%~1" -out "%~1.out.png",producing:
The resulting output image is now corrupted. Viewing the image, we no longer have a green background- it has become transparent. During optimization, the RGB image was reduced to indexed (correctly). As the transparent colour was never present in the image, the first palette entry is selected (in error!) as being transparent. This can be confirmed with TweakPNG. This may also occur with greyscale + transparency - but is untested. If the original image is edited, so that the
tRNSchunk references a present colour (e.g. magenta RGB(255,0,255)...), everything functions correctly.Expected behaviour is no transparency is set, when the defined transparent colour is not present.
This patch should fix the problem, but I'd like to take another day or two so that I can see what other changes I could make to the image reduction code. For example: opportunities to remove tRNS from grayscale images exists, just as with RGB images, but they are ignored.
Another thing that I want to point out is that this kind of fix ought to be backported to older OptiPNG versions also, e.g. to give a chance to downstream package maintainers to apply the fix even if they don't plan on upgrading to the latest version.
Forgive the >bump<...
Please could you release with a minimal fix? 🙏
Bump received. If I forgive you for doing absolutely nothing wrong, then please forgive me for my extraordinarily long delay.
If a release does not show up in a day or two (I mean it!) please do bump me again (I really mean it!!)
Update: I won't be ready for today, but I'm on track 🤞
Update: good news, and bad news, and good news.
The good news: the next release is slated to be the tip of the Git history, which I'm reconstructing in the same manner as I did with the pngcheck program. It's been going well so far.
The bad news: that Git history reconstruction is still not ready today.
The good news: my firm deadline for the next release is tomorrow. So if the Git history is ready, then I will publish it all, including the Git history. And if not, then I will just publish the 0.7.9 release as I did with all the previous ones.
And, finally, optipng-0.7.9 is up:
https://sourceforge.net/projects/optipng/files/OptiPNG/optipng-0.7.9/
I need to run a few more tests with the Windows builds (both 32-bit and 64-bit) until I'm 100% convinced they're ready for download, but it's past midnight here so I'll leave that (as well as the website update and the public announcement) for tomorrow.
The Git repo should be ready for next week -- or at least in my mind it is 🤞
D'oh! We're back to square one -- see my public announcement from two minutes ago.
So, I do have a proper fix, which consists in doing an assertion properly. All of my tests so far have been passing, and the release archives are ready to go --- except, this time around, I will run more tests instead of fewer.
The diff file below is relative to OptiPNG-0.7.8
So, I just announced the release of libpng-1.6.48, which, itself, had a kind-of-urgent fix waiting. After saying (so many times) that I will publish a new release, this time around I can say for a hard fact that there's no more PNG-related work that is more urgent than this optipng release.
In other words, this new release is next in line.
OptiPNG version 7.9.1 is out. I hope this will turn out to be what version 0.7.9 should have been. Tomorrow I will continue with the Windows build.
A temporary Git repo is also up.
I have performed quick tests with latest build and seems fixed. Thanks!
Feel free to close the issue as FIXED.