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?

荒凉一梦 提交于 2019-12-20 10:57:36

问题


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.


回答1:


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.




回答2:


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;
}



回答3:


This formular is not correct. The goal is to find unmultiplexed (r, g, b) that would latter result to the same multiplexed values (it is not possible to find the original r, g, b values, though.

However with the formular above we find for the example of

alpha = 100
r_premulti = 1

a reconstructed r = 2;

Latter if this r is multiplexed again we find 2 * 100 / 255 = 0 but we wanted r_premulti == 1 instead!!

The correct formular needs to round up. Example for r-component:

reconstruced r = ceiling(r_premulti * 255 / alpha)


来源:https://stackoverflow.com/questions/870690/just-in-theory-how-is-the-alpha-component-premultiplied-into-the-other-componen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!