如何将两个具有不同透明度值的颜色组合起来

12

我有两种颜色,c₀和c₁。它们具有可变的alpha、红色、绿色和蓝色值:(a₀,r₀,b₀,g₀)和(a₁,r₁,b₁,g₁)。我想知道是否有一个简单的公式来组合这些颜色以获得正确的新颜色(c₂)。

假设c₀覆盖c₁。如果它们具有相等的alpha值,则取它们的红、绿和蓝值的平均值即可。但是当alpha值不同时,我发现这种方法不起作用——似乎alpha决定了每种颜色的RGB值对最终颜色的"贡献"程度。

换句话说,

If a₀=a₁ then:
    a₂=a₀=a₁,
    r₂=(r₀+r₁)/2,
    g₂=(g₀+g₁)/2,
    b₂=(b₀+b₁)/2
Else:
    a₂=(a₀+a₁)/2,
    r₂=?,
    g₂=?,
    b₂=?

我相信答案在http://stackoverflow.com/a/2030560/1528942中给出。 - Grégoire C
非常好,非常感谢! - RapierMother
2个回答

29

简短回答:

如果我们想要将带有一些 alpha 值的 c0 放置在 c1 上方,则

a01 = (1 - a0)·a1 + a0

r01 = ((1 - a0)·a1·r1 + a0·r0) / a01

g01 = ((1 - a0)·a1·g1 + a0·g0) / a01

b01 = ((1 - a0)·a1·b1 + a0·b0) / a01

请注意,在颜色分量的公式中除以 a01 是很重要的。

详细回答:

当 c0 使用 alpha 值为 a0 覆盖不透明的 c1 时,颜色的基本公式为:

r0 over 1 = (1 - a0)·r1 + a0·r0

// g 和 b 分量相同

如果有另一种颜色 c2,而 c1 实际上不是不透明的,而是具有 alpha 值 a1,我们可以首先将 c1 叠加在 c2 上,然后再将 c0 叠加在结果颜色上。
r1 over 2 = (1 - a1)·r2 + a1·r1 r0 over (1 over 2) = (1 - a0)·((1 - a1)·r2 + a1·r1) + a0·r0 如果我们有一个颜色 c01,它与叠加 c1 和 c0 的结果相同,则如下:
r01 over 2 = (1 - a01)·r2 + a01·r01 让它们相等:
(1 - a01)·r2 + a01·r01 = (1 - a0)·((1 - a1)·r2 + a1·r1) + a0·r0

(1 - a0)·(1 - a1)·r2 + (1 - a0)·a1·r1 + a0·r0

所以

1 - a01 = (1 - a0)·(1 - a1) = 1 - ((1 - a0)·a1 + a0)

a01·r01 = (1 - a0)·a1·r1 + a0·r0


1
对于那些想要阅读更多的人,请查看维基百科关于Alpha合成的条目:https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending - Tenders McChiken
最后一个公式有一个问题: 如果a * r + b = c * r + d, 那么a = c,b = d吗?我有一个相反的例子: 2 * 3 + 3 = 1 * 3 + 6 - Xuyee Wang
@XuyeeWang 显然,我取a=c和b=d是因为我们需要对于任意的r值都有a * r + b = c * r + d。但是你的例子只适用于特定的r值,这里是3。如果你取另一个r值,比如4,那么2 * 4 + 3 = 11 != 1 * 4 + 6 = 10。 - vadzim

1

这是一个Python函数,当两种颜色具有相同的alpha时,它实现了上述答案:


def mix_two_colors_with_alpha(hex_color1, hex_color2, alpha=0.5):
    """Returns a color that's equivalent to displaying input color2 
    on top of input color1 where both have the given alpha.
    """

    hex_color1 = hex_color1.lower().strip("#")
    hex_color2 = hex_color2.lower().strip("#")
    result = "#"
    for i in 0, 2, 4:
        rgb_value1 = int("0x"+hex_color1[i:i+2], 16)
        rgb_value2 = int("0x"+hex_color2[i:i+2], 16)
        # r2 over r1 = (1 - a0)·r1 + a0·r2
        new_rgb_value = int((1-alpha) * rgb_value1 + alpha * rgb_value2)
        new_rgb_hex = hex(new_rgb_value).upper()
        result += new_rgb_hex[2:]
    return result

例子:

mix_two_colors_with_alpha("#FF80BF", "#004AC0", alpha=0.4) 

returns '#996ABF'

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