Menu

#90 Image corruption with invalid transparency

v1.0 (example)
closed-fixed
None
1
2025-06-10
2024-01-25
Andrew
No

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.

2 Attachments

Discussion

  • Andrew

    Andrew - 2024-01-25

    I have highlighted the defective pixel (that becomes full transparent), to red for clarity - attached.

     
  • Andrew

    Andrew - 2024-01-26

    I started to debug this before, but lost my notes...

    I observe the issue with non-paletted images (RGB/A), that have a tRNS chunk 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
  • Cosmin Truta

    Cosmin Truta - 2024-02-29

    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.

    optipng.exe -i0 -zc1 -zm8 -zs3 -f0 -force actions.png -out out.png
    

    The resulting file out.png is identical to actions.png.

    And then I tried the same but with actions-broken.png:

    optipng.exe -i0 -zc1 -zm8 -zs3 -f0 -force actions-broken.png -out out.png
    

    The resulting file out.png is not identical to actions-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:

    <html>
    <body bgcolor="red">
    <img src="actions.png">
    &nbsp;
    <img src="actions-broken.png">
    &nbsp;
    <img src="out.png">
    </body>
    </html>
    

    My conclusion, from my own experiments, is that actions-broken.png must have come from some other place, because I could not break actions.png by using optipng in the way that you reported.

     
  • Cosmin Truta

    Cosmin Truta - 2024-03-01
    • assigned_to: Cosmin Truta
    • Priority: 2 --> 1
     
  • Cosmin Truta

    Cosmin Truta - 2024-03-01

    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.

     
    👍
    1
  • Andrew

    Andrew - 2024-03-02

    Example 2

    To aid debugging, this test case is perhaps more obvious?
    See attached 'toolbar.png'. The image is RGB with a tRNS chunk 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:

    OptiPNG version 0.7.8
    Copyright (C) 2001-2023 Cosmin Truta and the Contributing Authors.
    
    ** Processing: P:\toolbar.png
    246x34 pixels, 3x8 bits/pixel, RGB+transparency
    Reducing image to 8 bits/pixel, 62 colors (1 transparent) in palette
    Input IDAT size = 2770 bytes
    Input file size = 2845 bytes
    
    Trying:
      zc = 9  zm = 8  zs = 0  f = 0         IDAT size = 1139
      zc = 9  zm = 8  zs = 1  f = 0         IDAT too big
      zc = 1  zm = 8  zs = 2  f = 0         IDAT too big
      zc = 9  zm = 8  zs = 3  f = 0         IDAT too big
    
    Selecting parameters:
      zc = 9  zm = 8  zs = 0  f = 0         IDAT size = 1139
    
    Output file: P:\toolbar.png.out.png
    
    Output IDAT size = 1139 bytes (1631 bytes decrease)
    Output file size = 1407 bytes (1438 bytes = 50.54% decrease)
    
    ** Status report
    1 file(s) have been processed.
    

    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 tRNS chunk 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.

     
  • Cosmin Truta

    Cosmin Truta - 2024-03-06

    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.

     
    • Andrew

      Andrew - 2025-04-03

      Forgive the >bump<...
      Please could you release with a minimal fix? 🙏

       
  • Cosmin Truta

    Cosmin Truta - 2025-04-03

    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!!)

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-04

    Update: I won't be ready for today, but I'm on track 🤞

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-07

    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.

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-11

    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 🤞

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-12

    D'oh! We're back to square one -- see my public announcement from two minutes ago.

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-17

    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.

     
  • Cosmin Truta

    Cosmin Truta - 2025-04-17

    The diff file below is relative to OptiPNG-0.7.8

     
  • Cosmin Truta

    Cosmin Truta - 2025-05-01

    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.

     
  • Cosmin Truta

    Cosmin Truta - 2025-05-20

    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.

     
  • Andrew

    Andrew - 2025-05-24

    I have performed quick tests with latest build and seems fixed. Thanks!
    Feel free to close the issue as FIXED.

     
  • Cosmin Truta

    Cosmin Truta - 2025-06-10
    • status: open --> closed-fixed
     

Log in to post a comment.

MongoDB Logo MongoDB