Skip to content

radiant: fix alpha channel for palette-with-transparency png

Thomas Debesse requested to merge illwieckz/netradiant:fixpng into master

I recently discovered a bug in netradiant related to some optimized png. Basically both textures showed there are not RGBA png, the one on the right is an 8-bit-palette-with-transparency png, the one on the left is an 1-bit-palette-with-transparency png. As you see, the transparency information is lost since what must be transparent is pitch black:

netradiant before

It looks like the bug is there:

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
        png_set_tRNS_to_alpha(png_ptr);
    }

/* --> here <-- */

    if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
        // Set the background color to draw transparent and alpha images over.
        png_color_16 my_background, *image_background;

        if (png_get_bKGD(png_ptr, info_ptr, &image_background)) {
            png_set_background(png_ptr, image_background,
                               PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
        } else {
            png_set_background(png_ptr, &my_background,
                               PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
        }

        // Add alpha byte after each RGB triplet
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
    }

First test checks if the png has a special tRNS chunk which is a chunk for simple transparency and if exists uses it as alpha channel.

Second test checks if the png has not an alpha mask, well, said otherwise, second test checks if the png is an RGB-without-A png. In that case, the RGB channels information are backgrounded by pitch black and the A channel is set to fully opaque.

The bad thing is that palette-based png are detected as RGB pictures, hence they are backgrounded and set opaque.

My solution is to put an else between two tests. I'm not a png wizard so I'm not sure to understand everything, but it fixed everything on my end and I haven't seen any visual corruption (not doing the else and commenting out the filler keeps transparency but corrupts data).

This is how looks those textures in netradiant now:

netradiant after

The palette-without-transparency png are still rendered fine, the caulk one seen above in texture browser being one of this kind.

Despite having an older png code (with some comments saying /* the following will probably bork on certain types of png images, but hey... */), q3map2 is not affected by this bug. As we can see, q3map2 is able to shadowcast those optimized png correctly:

in game in game

To completely validate q3map2's png support we would have to test palette-vithout-transparency png with a lightfilter effect. But that's outside of the current topic.

Edited by Thomas Debesse

Merge request reports