理论上来说:iPhone OS 中的 alpha 分量如何预乘到 PNG 的其他分量中,以及如何正确取消预乘?

发布于 2024-07-19 06:49:42 字数 643 浏览 11 评论 0原文

事实上,我认为有一个简单的方法可以实现这一目标。 我需要的是纯粹的阿尔法值信息。 为了进行测试,我有一个 50 x 55 像素的 PNG,其中每条边上都有一个 5x5 像素的矩形是完全透明的。 在这些区域中,alpha 必须为 0。在其他地方,它必须为 255。我非常确定我的 PNG 已正确创建,而且看起来也正确。

请告诉我这在理论上是否正确: 我创建了一个 CGImageRef,它只有 alpha 通道,没有其他任何东西。 这是通过 CGBitmapContextCreate 和 kCGImageAlphaOnly 作为参数来完成的。 CGBitmapContextGetBitsPerPixel(context) 返回 1,因此它表明每个像素实际上只有一个组件:所需的 alpha 值。 我一直在读到 CGBitmapContextCreate 将处理从给定图像到新创建的上下文的所有转换。 我的图像以前是具有透明度的 PNG-24,但 Xcode 中的 pngcrunch 似乎以某种方式转换了它们。

所以,仅从理论上来说:此时我是否有机会获得正确的、未预乘的 alpha 值? 我得到的值似乎几乎匹配,但在一个大的 5x5 透明正方形中,我得到的值包括 19、197、210、0、0、0、98 等。 如果它们是真的,我就必须从图像中看到一些东西。 图像本身是纯蓝色的。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

东走西顾 2024-07-26 06:49:42

预乘不会影响 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

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.

a√萤火虫的光℡ 2024-07-26 06:49:42

由于预乘颜色值很简单:

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

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;
}
总攻大人 2024-07-26 06:49:42

这个公式不正确。 目标是找到未复用的 (r, g, b),后者稍后会产生相同的复用值(尽管不可能找到原始的 r, g, b 值。但是,

通过上面的公式,我们可以找到示例 重建后的

alpha = 100
r_premulti = 1

r = 2;

稍后,如果再次对 r 进行复用,我们会发现 2 * 100 / 255 = 0,但我们需要 r_premulti == 1

! r 组件:

reconstruced r = ceiling(r_premulti * 255 / alpha)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文