views:

420

answers:

2

Actually, I thought that there would be an easy way to achieve that. What I need is pure alpha value information. For testing, I have a 50 x 55 px PNG, where on every edge a 5x5 pixel rectangle is fully transparent. In these areas alpha has to be 0.Everywhere else it has to be 255. I made very sure that my PNG is created correctly, and it also looks correctly.

Please tell me if this is theoretically correct: I created an CGImageRef that has only the alpha channel and nothing else. This is done with CGBitmapContextCreate and kCGImageAlphaOnly as param. CGBitmapContextGetBitsPerPixel(context) returns me 1, so it indicates me that I really have only one component per pixel: The desired alpha value. I've been reading that CGBitmapContextCreate will handle all the conversion from the given image to the new created context. My image was previously PNG-24 with transparency, but pngcrunch from Xcode seems to convert them somehow.

So, just in theory: Do I have any chance to get to the correct, unpremultiplied alpha at this point? The values I get seem to almost match, but in a big 5x5 transparent square I get values like 19, 197, 210, 0, 0, 0, 98 and so on. If they were true, I would have to see something from the image. The image itself is solid blue.

+4  A: 

Premultiplication doesn't affect the alpha channel, it affects the color channels.

The formula for raster compositing (putting one raster image over another) is:

dst.r = src.r * src.a + dst.r * (1.0 - src.a);
dst.g = src.g * src.a + dst.g * (1.0 - src.a);
dst.b = src.b * src.a + dst.b * (1.0 - src.a);

Premultiplication cuts out the first multiplication expression:

dst.r = src.r′ + dst.r * (1.0 - src.a);
dst.g = src.g′ + dst.g * (1.0 - src.a);
dst.b = src.b′ + dst.b * (1.0 - src.a);

This works because the source color components are already multiplied by the alpha component—hence the name “premultiplied”. It doesn't need to multiply them now, because it already has the results.

unpremultiplied alpha

The alpha component itself is never premultiplied: What would you multiply it by? The color components are premultiplied by the alpha.

Peter Hosey
I think I get it now. Alpha remains clean. But in praxis, when I create an PNG that has totally transparency (like a clean piece of high-quality non-colored glass), pngcrunch does something to my PNG. After I read the alpha values, some are 0 like they should, but some are 199 or even bigger, which makes absolutely no sense. If they were true, I would have to see some pixels from that image. White image made totally transparent. Black background in iPhone. Nothing shines through, but like 50% of all alphas are bigger than 100... it's really strange.
Thanks
As I said on your other question, you're looking at the data incorrectly, and mistaking other components (notably blue) for alpha.
Peter Hosey
One other thing: pngcrush has nothing to do with the contents of a bitmap context. A bitmap context contains pure pixels in the format you asked for; it is completely divorced from any and all external representations, past and future.
Peter Hosey
+2  A: 

Since premultiplying color values is a simple as:

r = (r * a) / 255;
g = (g * a) / 255;
b = (b * a) / 255;

Getting the inverse would be:

if (a > 0) {
    r = (r * 255) / a;
    g = (g * 255) / a;
    b = (b * 255) / a;
}
rpetrich
Nice! So alpha is always "untouched"? I thought that I would also have to calculate something to get the correct alpha value.
Thanks
Yes, the alpha is untouched. Premultiplying color channels is just an optimization to cut down the number of multiply operations the graphics chip has to perform.
rpetrich