理论上:在iPhone OS中,alpha分量是如何与PNG的其他分量预乘的?如何正确地将其取消预乘?

3
实际上,我认为应该有一种简单的方法来实现这个目标。我需要的是纯阿尔法值信息。为了测试,我有一个50 x 55像素的PNG图像,在每个边缘都有一个5x5像素的矩形完全透明。在这些区域里,阿尔法值必须为0。其他地方的阿尔法值必须为255。我非常确定我的PNG图像被正确创建,并且看起来也正确。
请告诉我这是否理论上是正确的: 我创建了一个只有阿尔法通道而没有其他内容的CGImageRef。这是通过使用CGBitmapContextCreate和kCGImageAlphaOnly作为参数完成的。 CGBitmapContextGetBitsPerPixel(context)返回1,因此它告诉我每个像素只有一个组件:所需的阿尔法值。 我已经读到CGBitmapContextCreate将处理从给定图像到新创建的上下文的所有转换。我的图像之前是带有透明度的PNG-24格式,但Xcode中的pngcrunch似乎会进行某种转换。
那么,仅在理论上:我有任何机会在这一点上获得正确的、未预乘的阿尔法值吗?我得到的值似乎几乎匹配,但在一个大的5x5透明正方形中,我得到的值如19、197、210、0、0、0、98等。如果它们是真实的,我应该能从图像中看到一些东西。这个图像本身是纯蓝色的。
3个回答

8

预乘并不影响alpha通道,它影响的是颜色通道。

栅格合成(将一个栅格图像放在另一个上面)的公式如下:

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

预乘消除了第一个乘法表达式:

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

这个可以工作的原因是源颜色分量已经被 alpha 分量乘以,因此其名为 "预乘法"。现在不需要再次乘以它们,因为它已经得到了结果。
未预乘的 alpha。
alpha 分量本身永远不会被预乘:你会乘以什么?颜色分量是通过 alpha 预乘的。

我现在明白了。Alpha 保持干净。但是在实践中,当我创建一个完全透明的 PNG(就像一块高质量无色玻璃),pngcrunch 对我的 PNG 进行了某些处理。在读取 Alpha 值后,有些值为 0,就像它们应该的那样,但有些值为 199 或更大,这根本没有意义。如果它们是真实的,我应该能够看到来自该图像的一些像素。白色图像完全透明。iPhone 上的黑色背景。没有任何东西透过去,但大约 50% 的 Alpha 值都大于 100... 真的很奇怪。 - Thanks
正如我在你的另一个问题中所说,你正在错误地查看数据,并将其他组件(特别是蓝色)误认为是 alpha。 - Peter Hosey
另外一件事:pngcrush与位图上下文的内容无关。位图上下文包含以您所要求的格式为纯像素;它与所有过去和未来的外部表示完全脱离。 - Peter Hosey

6

由于预乘颜色值非常简单,只需执行以下操作:

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

获得反向结果的方法是:
if (a > 0) {
    r = (r * 255) / a;
    g = (g * 255) / a;
    b = (b * 255) / a;
}

不错!所以alpha始终是“未改变的”吗?我以为我还需要计算一些东西才能得到正确的alpha值。 - Thanks
是的,alpha 通道没有改变。预乘颜色通道只是一种优化方式,可以减少图形芯片需要执行的乘法操作数量。 - rpetrich

1
这个公式不正确。目标是找到未复用的(r,g,b)值,使其最终结果与相同的多路复用值相同(虽然无法找到原始的r,g,b值)。
然而,使用上述公式,我们可以找到以下示例的值:
alpha = 100
r_premulti = 1

重新构建 r = 2;

如果再次进行多路复用,我们会发现 2 * 100 / 255 = 0,但我们希望 r_premulti == 1!

正确的公式需要进行 四舍五入。例如,对于 r 分量:

reconstruced r = ceiling(r_premulti * 255 / alpha)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接