GNOME Bugzilla – Bug 637413
Saving indexed png with transparency removes one unused color from the colormap
Last modified: 2017-12-31 23:50:48 UTC
SO: Ubuntu Lucid Lynx Symptoms: Saving png one and only one unused color is removed from the colormap. Steps to reproduce: 1. New image rgb 2. Change to indexed mode with optimum palette 3. Add alpha channel 4. Erase a piece of background 5. Add a color to the colormap (example black) 6. Save the image and close it 7. Open again and black is not in the colormap More info: * If there are several unused colors one and only one color is removed, that's why I think this isn't an expected behavior. * Without alpha channel no colors are removed.
Hi! It happens to me too! Steps: 1. Open a RGB image. 2. Convert it to indexed. 3. Import the generated palette to gimp palettes. 4. Apply the palette to image (works fine). 5. Close image. 6. Open image again. 7. Apply the same palette to same image. Not Work. I an using GIMP 2.6.11 and bug it happens to. I Try version 2.7.3 (unstable) and the bug persists. If the indexed PNG image with alfa was saved, the same palette is not correctelly applied anymore. It not occur with GIF. I am using ubuntu linux too.
Created attachment 210535 [details] [review] patch It does not seem to be an error, since this behavior is documented in respin_cmap() in file-png.c. However, I agree that it seems weird. We should either remove all unused colors or try not to remove any (if there are less than 256 colors in the palette). The proposed patch always removes all unused colors.
I agree that the behaviour should be consistent, remove all or not remove any. I rather not to remove any because when I first encountered this problem I was trying to save a set of frames to png files, all sharing the same colormap, that way I could achieve good compression storing only the deltas between frames. But sometimes there were different colors between frames. At that time a used the workarround of always add a dummy color that the plugin would consume, but that's why I think when you choose a colormap the saving plugin should respect it.
If you remove the "unnused" colors it will break the consistent/relation with the color table/color map previously created. What the purpose to create/manage a color table, if you cannot use it again when you close/open the image? Please do note remove the colors, without ask the user. It not happens in previous versions of GIMP. I think it is a bug.
Created attachment 210654 [details] [review] patch: try not to remove any unused color pmoleri, that makes sense, even though I am not sure many users have the problem you described :) This new patch does not remove any unused color if there is less than 256 colors in the palette.
Nice. Indeed, my use case was kind of peculiar :) But as a general rule, is nice when the application keeps the colormap, you always have the option of generating an optimal pallete. To "remove unused colors" would be an improvement as an option in the save dialog, buy everyone can live without it.
Alexis, why do we at all fill the colormap to always contain 256 colors (that's what the patch does, right?). Can't we simply export the colormap as-is and done?
(In reply to comment #7) Michael, if I understood correctly the patch, it doesn't fill the colormap, it just looks if it's under 256 colors and adds *one* to use as transparency. And only if the colormap is full it looks for the first unused color to use as transparency.
Uh, seems like I wasn't in the CC list. Right now find_unused_ia_color(): 1) looks for an unused color and removes it (line 1831); 2) checks if there is still room in the palette (line 1840). The patch simply reverse those two actions, so we won't remove a color if we don't need to.
*** Bug 670177 has been marked as a duplicate of this bug. ***
Created attachment 226377 [details] Comparison of palettes before and after opening and saving an indexed png Confirming this for GIMP 2.82 on Win7 and Mac.
*** Bug 687309 has been marked as a duplicate of this bug. ***
Comment on attachment 210654 [details] [review] patch: try not to remove any unused color This patch seems simple enough, and it still applies cleanly - and it likely keeps a few files from being changed more than necessary.
Adding the transparent colour to the end is probably the best behaviour, but there's another interesting problem here: if the image has a full colourmap and *already* contains a transparent colour in the palette (in e.g., OpenXcom's case, this is always #0 in the palette), the current builds of GIMP still discard it even though it *is* the transparent colour, and assign a new one anyway. Thus, the transparent colour gets discarded and a brand new transparent colour gets assigned at the end of the palette instead, shifting the entire palette one entry to the left. In OXC this is non-fatal, simply darkening the image -- except for the near-black shades, which wind up shifting into the next row of colour information -- but GIMP has always been my go-to for spriting and it's a shame that it fails so badly here. Is there a way to improve the behaviour such that it checks whether the transparent pixels in the image share a common colour in the palette before it decides to assign a new transparent colour? An RGBA image which includes varying shades of alpha in a percentage of the pixels might degrade in a less than optimal manner, but any other image with a fixed palette will perform ideally. I suppose a brute-force solution could simply scan the image for the first transparent pixel and, once found, see if the same RGB data is used anywhere else in the image in a non-transparent pixel. If not, that colour should be yielded as the transparent colour and there is no need to assign a new one. Since most images with transparency have the transparent pixels close to the corners this would usually be O(1) and no worse than O(n) for the number of pixels in the image. One would have to intentionally design a PNG to have a single transparent pixel in the farthest corner to make this operation take a large number of operations and it would still be no more than a quarter-second or so for a typical image.
Jeremy, did you try with the proposed patch? (attachment 210654 [details] [review]) I believe it should fix the issue you describe. If it does not, can you post an image and the steps to reproduce your bug? Some more info I found about PNG and GIMP: In PNG files, the transparent colors are always at the beginning of the palette. In PNG files exported by GIMP, there is at most one transparent color, and it is always the first color of the palette. When loading an image, load_image() (lines 1170 to 1190 of file-png.c) removes all fully transparent colors from the palette and shifts all other colors toward the beginning. When exporting this image, find_unused_ia_color() sees that the palette is not full (because the transparent color was removed) and appends a new transparent color at the end. Then respin_cmap() puts the transparent color at index 0 and shifts all other colors toward the end. So the palette of the exported image should be the same as in the original image.
The patch still applies, is very localized and I got a branch based on master for it, so I could push it instantly.
Applies, builds, produces a working file-png plug-in and it's got the 2.10 milestone: commit 8b29687353e38896bc8d5ee3e7d69ae0bf0f4471 (HEAD -> master, bug-637413) Author: Alexis Wilhelm <alexiswilhelm@gmail.com> Date: Mon Mar 26 20:40:25 2012 +0200 Bug 637413 - Saving indexed png with transparency removes one unused color from the colormap