Как совместить два цвета с различными значениями альфа

У меня есть два цвета, 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'
Другие вопросы по тегам