Как совместить два цвета с различными значениями альфа
У меня есть два цвета, C₀ и C₁. Они имеют переменные значения alpha, red, green и blue: (a₀, r₀, b₀, g₀) и (a₁, r₁, b₁, g₁). Мне интересно, есть ли простая формула для объединения этих цветов, чтобы получить правильный новый цвет (c₂).
Допустим, что c₀ перекрывает c₁. Я понимаю, что если бы они имели равные альфа-значения, то усреднение их сравнительных значений красного, зеленого и синего цветов помогло бы. Но когда значения альфа отличаются, я замечаю, что это не работает должным образом - кажется, альфа определяет уровень, на котором значения 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₂=?
2 ответа
Короткий ответ:
если мы хотим наложить 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
Обратите внимание, что деление на01 в формулах для компонентов цвета. Это важно.
Длинный ответ:
Основная формула для цвета, когда c0 накладывает непрозрачный c1 на альфа a0,
r0 больше 1 = (1 - a0) · r1 + a0· r0
// то же самое для компонентов g & b
Таким образом, если есть другой цвет c2 и c1, на самом деле не непрозрачный, но имеет альфа a1, мы можем наложить сначала c1 поверх c2, а затем c0 поверх полученного цвета.
r1 над 2 = (1 - a1) · r2 + a1· r1
r0 over (1 over 2) = (1 - a0) · ((1 - a1) · r2 + a1· r1) + a0· r0
Если бы у нас был цвет c01, который перекрывает c2 с тем же результатом, что и наложение сначала c1, а затем c0, это было бы так:
r01 более 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
Это функция Python, которая реализует приведенный выше ответ, когда оба цвета имеют одинаковую альфу:
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'