Saturday, October 17, 2015

transparency - Using GIMP, can you "erase" a color?


I'm presently working on an iOS application and I am attempting to reverse engineer their standard alert dialog window. I have managed to figure out what the alpha value on the background it uses is through some color sampling against a solid black view, and a solid white view.


Given this information, using GIMP is it possible to just "erase" the background color, so that I am only left with the original, unblended alert background?


I only have the alert view in image form as a screenshot from a running app.



Answer



Yes, it's possible. Let me outline how it's done, using this image from Wikimedia Commons (by ed_g2s, licensed as CC-By-SA 3.0) as an example:



PNG transparency demonstration image by ed_g2s, licensed as CC-By-SA 3.0




  1. Open the black and white background versions as layers of the same image (using Open as Layers... or just open both and copy-and-paste one into the other). Move the white layer above the black layer if it's not already that way. The two layers should looks something like this:


    Demonstration image with black background Demonstration image with white background




  2. Take the difference of the layers: clone the black layer (you'll need it later), change the white layer's layer mode to "difference" and merge it down. Invert the result. This gives you the alpha channel of the original image.


    Reconstructed alpha channel


    Edit: If your backgrounds are not black and white, the inverted difference layer won't have a black background. To fix that, first desaturate the layer (using whichever mode that gives you the best contrast) and then use Colors → Auto → Normalize to make the background black. You could also use the Channel Mixer instead, but it's a little trickier to use.



    (Normalize above works if the alpha channel you're recreating has at least some parts with 100% opacity; if the image you're recreating is everywhere translucent, you can use Colors → Levels... to set only the black point instead.)


    If you don't already have one, you also need to create a version of your image with a black background for the next step. To do that, use the following extra steps:



    • Pick whichever original version has the darker background. Create a new layer on top of it filled with its background color.

    • Clone the difference layer and re-invert it so that it has a white background. Place this layer on top of the new solid-color one you just created, set its layer mode to "multiply" and merge it down.

    • Finally, change the resulting layer's mode to "subtract" and merge it down onto the layer with the original image. This should subtract away the original background, leaving you with the image on a black background.




  3. If we were using an image format with pre-multiplied alpha, we'd be more or less done now. But since we aren't, we still need to de-multiply the RGB channels. To do that, clone the alpha layer we created in the previous step (or just copy it to the clipboard), set its layer mode to "divide" and merge it down with the black-background layer your cloned before step 2. The result should look like this (compare with the original black-background version to see the difference):



    De-multiplied RGB channels




  4. Now, add a layer mask to the resulting layer, select the mask and paste the alpha layer into it. The result should now look more or less like the original transparent image. Finally, to turn the mask into a proper alpha channel, you can apply it (but GIMP's PNG export will do that for you even if you don't). And there you go — one reconstructed transparent PNG ready to go:


    Reconstructed image with transparency




Of course, this technique really requires that you have versions of the image on pure black and pure white backgrounds. If the backgrounds are a little bit off, similar methods may still be usable, but you may need to do additional color adjustments and the results may not be as perfect. (Edit: See additions to step 2 above. The amended instructions should work with backgrounds of any color, as long as they're solid colors.)




Ps. GIMP does also have a "Color Erase" feature (as a blend mode for the Bucket Fill tool, or as Color to Alpha... for the whole image), which is useful for reconstructing transparency when you have only one version of the image on a solid color background. However, unless used carefully, it does have a tendency to produce output that is rather more transparent than you'd probably want it to be.



Pps. If you compare the original and reconstructed images very carefully, you'll see that they're not exactly identical — some color values are off by 1/256 or so. That's because of how GIMP's "divide" layer mode works: rather than calculating the true inverse of the alpha multiplication, which would be output = (255 × input) / layer, it actually calculates output = (256 × input) / (layer + 1). This mismatch, which is ostensibly done to avoid dividing by zero, means that some of the colors may round to a slightly different value than they should. Alas, I know of no way around this, other than patching GIMP, writing a plugin to do the division the way we want it, or using some other program. Fortunately, though, the color difference is rarely if ever actually perceptible by the human eye.


No comments:

Post a Comment

technique - How credible is wikipedia?

I understand that this question relates more to wikipedia than it does writing but... If I was going to use wikipedia for a source for a res...