半透明和透明背景下的混合模式

8
一般来说,“正常”混合模式的方程式如下:
D = Sa * S + D * (1.0 - Sa)

其中D是目标颜色,Sa是源alpha,S是源颜色。

现在,这在完全不透明的目标情况下可以正常工作,但我想知道如果目标是半透明或完全透明的情况下,你会如何处理。

当将源混合到完全透明的目标上时,源像素(一个像素包含颜色和alpha)将保持不变,不会像之前的方程式中那样混合。如果目标背景完全不透明,则应用上述方程式,但我找不到一种好的方法来处理目标alpha介于0和1之间的情况。

例如,如果您在透明背景上混合50% alpha的白色像素,则颜色不应趋向于该透明颜色值(这几乎是未定义状态),目标颜色应为纯白色,而不是50%(经过alpha乘法后),这是应用上述方程式后得到的结果(如果将D设置为与S相同的颜色,则这是我考虑过的一些内容)。

3个回答

12

这个方程式是通用混合方程的简化版。它假设目标颜色是不透明的,因此省略了目标颜色的 alpha 值。

D = C1 * C1a + C2 * C2a * (1 - C1a)

其中 D 是结果颜色,C1 是第一个元素的颜色,C1a 是第一个元素的 alpha 值,C2 是第二个元素的颜色,C2a 是第二个元素的 alpha 值。目标 alpha 值的计算方式为:

Da = C1a + C2a * (1 - C1a)

导出的颜色已经与透明度进行了预乘。要将颜色恢复为未经过预乘的值,只需通过导出的透明度Da进行除法运算即可。


这是不起作用的。例如,如果目标颜色为黑色,源颜色为白色。目标alpha值为0,源alpha值为0.5,则最终结果为D = 1.0 * 0.5 + 0.0 * 0.0 * (1.0 - 0.5),这是1.0 * 0.5,就像乘以源颜色的alpha值。这不是我想要的,如果目标alpha值为0,我希望源颜色保持不变。 - Nicolas Goy
这就是混合模式的工作原理。如果您想要不同的行为,您需要不同的混合模式。还有许多其他的混合模式。在http://illusions.hu/effectwiki/doku.php?id=list_of_blendings上有一个很好的列表。 - Mr. Berna
2
此外,生成的颜色是通过 alpha 进行预乘的。您可以通过将生成的颜色除以生成的 alpha 来恢复为未预乘的颜色。当我进一步思考时,我认为这正是您想要的。 - Mr. Berna
1
好的,我太蠢了,你是对的,解决方案就是最后除以得到的 alpha 值。谢谢。 - Nicolas Goy

1
我发现这个答案很有帮助,当将相同的公式应用于alpha通道时,它似乎按预期工作。
这里修改以显示扩展版本:
int blend(unsigned char result[4], unsigned char fg[4], unsigned char bg[4] {
    unsigned int alpha = fg[3] + 1;
    unsigned int inv_alpha = 256 - fg[3];
    result[0] = (unsigned char)((alpha * fg[0] + inv_alpha * bg[0]) >> 8);
    result[1] = (unsigned char)((alpha * fg[1] + inv_alpha * bg[1]) >> 8);
    result[2] = (unsigned char)((alpha * fg[2] + inv_alpha * bg[2]) >> 8);
    result[3] = (unsigned char)((alpha * fg[3] + inv_alpha * bg[3]) >> 8);
    // result[3] = 0xff;
}

这对于快速而简单的代码很有效,但也有更快的方法,正如上面的答案所评论的那样,也在这里这里中提到。

嗯,实际上将 #00000000 与 #ffff0000 混合会得到 #41800000 的结果,而不是预期的 #ffff0000。 - Dev

0

大多数混合公式用于静态图像,其中目标颜色的 alpha 值未存储。如果 alpha 可用,则最终 alpha 将简单地成为源 alpha 和目标 alpha 的算术平均值

您可以计算平均 alpha,然后在公式中直接使用它代替 'Sa'。

能告诉我们这是用来做什么的吗?


1
计算目标alpha不是问题,问题是颜色的合成。这个任务要求将一个半透明的图像叠加在第二个半透明的图像上,并将结果保存为具有透明度的PNG文件。在Photoshop中,我可以通过加载两个图像,合并两个图层并保存为PNG来实现这个功能。 - Nicolas Goy
我仍然不明白为什么对 alpha 通道取平均值不能产生正确的颜色? - tplaner
1
想象一下0 alpha和0.5叠加,结果值应该是0.5,但实际上却是0.25。 - Dev

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