GNOME Bugzilla – Bug 55700
Indexed PNG does not save alpha
Last modified: 2009-08-15 18:40:50 UTC
Load logo.gif from the Linux source (Tux penguin) - a transparent GIF. Save it in PNG. The resulting PNG will have blue in place of transparency, as seen by reloading the image with Gimp. Maybe PNG does not supported transparent indexed images? Then Gimp should at least warn the user, which it does not currently.
Now this is interesting... I just tried it, and indeed the logo.gif is loaded correctly (showing the transparency), but saving it as PNG and re-loading the file shows that the transparent areas have been converted to blue (which happens to be the "transparent color" of the original GIF image). But PNG does support indexed images with transparency, and the Gimp can even save these correctly. If you take the image logo.gif, convert it to RGB and then back to indexed mode and save it as PNG, then the results will be correct: you will get an indexed PNG image with transparency. The same happens when you create an image from scratch. So this seems to be a problem that occurs only when you open a GIF image and save it as PNG. This could be very annoying for those who want to use the Gimp to "Burn all GIFs"... I do not know if the bug is in the core or in the plug-ins. This is very strange...
I can reproduce this. It may or may not be possible to fix this, the Gimp and PNG/GIF do not agree about how transparency works for INDEXED class images and the result is that even though gif2png can do this translation seamlessly there is no guarantee that I can do it with Gimp in the middle. I will investigate this weekend, changes may be needed to the GIF plug-in(s) if I can't solve this from PNG alone.
still present in gimp-1.2.2-pre2
Sorry for the noise, I just bumped up the version number and changed my email address.
*** Bug 86627 has been marked as a duplicate of this bug. ***
This bug is still present in the current stable version (1.2.4-pre1) and in the developers version (see bug #86627). Questions to Nick (or anybody else reading this): What would be necessary in order to fix this in 1.2.4? Is it possible to fix this problem without changing the INDEXEDA mode in the core? Or is it something that can be fixed in the PNG plug-in alone?
It would be very nice to fix this in 1.2.4. Can anyone answer the previous questions?
I've done a bit of hunting on this one and basically this happens if you have a full (256 colour) palette, but not if there's space in the palette. The code responsible is in respin_cmap in the png plug-in - if the palette passed in is full (as it is usual;ly in a gif, with one colour allocated to transparency), the following happens... 1013 if (colors < 256) { /* spare space in palette :) */ Does stuff right, including... 1024 png_set_tRNS(pp, info, (png_bytep) trans, 1, NULL); 1025 png_set_PLTE(pp, info, (png_colorp) after, colors + 1); 1026 } else { Does basically nothing 1027 png_set_PLTE(pp, info, (png_colorp) before, colors); 1028 } There's an attempt to hack around this later on which doesn't appear to work (there's no call to png_set_tRNS so it can't really be expected to) 956 /* Forgot this case before, what if there are too many colors? */ 957 } else if (info->valid & PNG_INFO_PLTE && bpp == 2) { 958 for (i = 0; i < num; ++i) { 959 fixed= pixels[i]; 960 for (k = 0; k < drawable->width; ++k) { 961 fixed[k] = fixed[k*2]; 962 } 963 } Basically the fix here should be in respin_cmap. Either we figure out what the transparency colour is (by getting the rgb value beneath the alpha=255 bits, I guess) and set that as transparent in the png too, or we manually get all the values of the image which aren't transparent, and generate a new palette, adding transparency when we're done. As far as I can tell this is what gif2png does. I'm not exactly sure how this would be fixed, in terms of code, looking at libpng and the indexed palette stuff now. Also how would people think the best way to generate a palette for the image excluding the transparent bits? Cheers, Dave.
Most of what I said yesterday is horse buckey. The fix is considerably easier than that. In fact, most of the code is borrowed from gif.c. The fis is for each pixel, if pixel is not transparent, set a flag on the index associated with this pixel to say that it's used in the image If there is an index which is not sued in the image, use it for transparency. otherwise require some user action (either "save without transparency" or tell them to re-index the image with at most 255 colours). This is what gif does, and png will do it too in a few minutes. Will commit to 1.3 once I've tested it a bit. Dave.
Why don't you just iterate over the palette until you find an unused color? Setting a used flag on each color and then searching for an unused entry sounds like a rather complicated approach to simple problem.
Forget what I said above...
Fixed in CVS. Will commit to 1.2 as well (without the verbosity) unless there are objections. Attaching patch. Cheers, Dave.
Created attachment 11003 [details] [review] Find unused index in the indexed palette for transparency information
Grumble. Doesn't work properly. Not sure why. Images with full palettes or unused colours end up with extra transparency. Will fix it tomorrow (11/9/2002). Cheers, Dave.
Back from holiday, taken care of the backlog, and got around to fixing the fix. Attaching the patch for 1.3 (which has now been committed) - will commit to 1.2 in a couple of days if there are no objections. Dave.
Created attachment 11553 [details] [review] Find unused colour in palette, set it to transparency, and make sure that the indexes are written out correctly at save time. Repairs problem with last patch.
Can I assume I can commit this to 1.2 and mark it as resolved? Dave.
I have no authority over what should be commited to CVS, but I think that you can commit it. However, maybe you should consider adding some #ifdefs around the g_print() statements so that the users do not get these messages unless they have activated some debugging options.
Yes, please make sure there's no debugging output in the final version. I was hoping that Nick Lamb would give you his OK for the patch but since noone complained about the patch being in the HEAD branch so far, I'd say go ahead and commit it to the stable branch as well.
Dave, if you close a bug-report, could you please add a comment why you are closing it. The best thing is probably to paste the ChangeLog entry like this: Fixed in the stable branch as well: 2002-10-29 Dave Neary <bolsh@gimp.org> * plug-ins/common/png.c: Back-ported patch from HEAD to close bug #55700.
*** Bug 78648 has been marked as a duplicate of this bug. ***
The fix is part of the stable release 1.2.4. Closing this bug.
To me this appears is still broken. Loading http://entropymine.com/jason/testbed/pngtrans/pal_bk.png will make it display in layer window thumbnail preview correctly. In the WM title and the selector too. But not in the image canvas. Saving it to file and loading discards the alpha information. (screenshot attached) Can you reopen, please?
Created attachment 17663 [details] Screenshot of GIMP opening the URL above. Notice the thumbnail preview rendered correctly.
Grumble. I trusted Dave's comments and ChangeLog entries. But it looks like the bug is still open. But fixing this bug correctly with probably require a new mode in the core, because I don't think that the current implementation of INDEXEDA will work. I would be glad to be wrong, though. So I am moving the target milestone from 1.2.4 to 1.2.6, hoping that I am wrong.
GIMP's internal representation of indexed images with alpha is pretty weird. There is a colormap w/o alpha information and an alpha channel. I'm not really sure why the display code tries to give the impression that the alpha channel has 1 bit only but this was probably done in order to improve the support for GIF images with alpha channel. GIMP is not actually suited well for indexed PNG files. The bug here is that the PNG plug-in does not warn the user that GIMP can not handle this properly and that the preview code doesn't do the same alpha thresholding that the display code does. But one could also argue that the display code is wrong here.
As Sven said, this is a rendering problem, and is a limitation of the GIMP core for INDEXEDA images. Not sure why it was done this way, but anyway... The PNG bug mentioned here is a different problem. This bug continues to be fixed :) For the record, the GIMP save routines only handle pngs with GIF type transparency, that is, one colourmap entry which corresponds to completely transparent. This also is a limitation caused by the GIMP's internal representation of indexed images - we should have RGBA palettes, and only convert to GIF type palettes in the relevant save routines. Cheers, Dave.
OK, let's mark this bug as CLOSED and re-open the discussion about indexed PNG with full alpha (instead of 1-bit alpha) in bug #86627.