Search code examples
iphonecocoapngcore-graphicspng-24

Just in theory: How is the alpha component premultiplied into the other components of an PNG in iPhone OS, and how can it be unpremultiplied properly?


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.


Solution

  • 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.