Reputation: 369
I have two colors, c₀ and c₁. They have variable alpha, red, green and blue values: (a₀, r₀, b₀, g₀) and (a₁, r₁, b₁, g₁). I'm wondering if there is a simple formula for combining these colors to obtain the correct new color (c₂).
Let's say that c₀ overlays c₁. I understand that if they had equal alpha values, then averaging their comparative red, green and blue values would do the trick. But when the alpha values differ, I'm noticing this doesn't work properly—it seems alpha determines the level at which each color's RGB values "contribute" to the final color.
Otherwise stated,
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₂=?
Upvotes: 13
Views: 10796
Reputation: 1281
This is a python function that implements the above answer when both colors have the same 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
Example:
mix_two_colors_with_alpha("#FF80BF", "#004AC0", alpha=0.4)
returns '#996ABF'
Upvotes: 1
Reputation: 521
Short answer:
if we want to overlay c0 over c1 both with some alpha then
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
Note that division by a01 in the formulas for the components of color. It's important.
Long answer:
The basic formula for the color when c0 overlays opaque c1 with alpha a0 is
r0 over 1 = (1 - a0)·r1 + a0·r0
// the same for g & b components
So if there is another color c2 and c1 actually is not opaque but has an alpha a1 we can overlay first c1 over c2 and then c0 over the resulting color.
r1 over 2 = (1 - a1)·r2 + a1·r1
r0 over (1 over 2) = (1 - a0)·((1 - a1)·r2 + a1·r1) + a0·r0
If we had a color c01 which overlays c2 with the same result as overlaying first c1 and then c0 it would be like this:
r01 over 2 = (1 - a01)·r2 + a01·r01
Ok, let's make them equal:
(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
so
1 - a01 = (1 - a0)·(1 - a1) = 1 - ((1 - a0)·a1 + a0)
a01·r01 = (1 - a0)·a1·r1 + a0·r0
Upvotes: 31