Режим смешивания на прозрачном и полупрозрачном фоне - PullRequest
7 голосов
/ 12 ноября 2009

В общем, «нормальное» уравнение режима наложения выглядит следующим образом:

D = Sa * S + D * (1.0 - Sa)

, где D - цвет назначения, Sa - исходный альфа, а S - исходный цвет.

Теперь, это прекрасно работает с полностью непрозрачным пунктом назначения, но я хотел бы знать, как бы вы справились с этим с полупрозрачным пунктом назначения.

При смешивании источника с полностью прозрачным местом назначения исходный пиксель (пиксель, являющийся цветом и альфа-каналом) будет неизменным и не будет смешиваться, как в предыдущем уравнении, и если фон назначения полностью непрозрачен, вышеприведенное уравнение должно быть применяется, но я не могу найти хороший способ справиться с ситуациями, когда целевая альфа находится между 0 и 1.

Например, если вы смешиваете белый пиксель с 50% альфа на прозрачном фоне, цвет не должен стремиться к этому значению прозрачного цвета (которое более или менее находится в неопределенном состоянии), цвет назначения должен быть полностью белым а не 50% (после альфа-умножения), что вы и получаете после применения приведенного выше уравнения (если D сделан в том же цвете, что и S, о чем я думал).

Ответы [ 3 ]

8 голосов
/ 12 ноября 2009

Это уравнение является упрощением общего уравнения смешивания. Предполагается, что цвет назначения непрозрачен, и поэтому отбрасывает альфа-член цвета назначения.

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

где D - результирующий цвет, C1 - цвет первого элемента, C1a - альфа первого элемента, C2 - цвет второго элемента, C2a - альфа второго элемента. Альфа-адресат рассчитывается по формуле:

Da = C1a + C2a * (1 - C1a)

Результирующий цвет предварительно умножается на альфа. Чтобы восстановить цвет до неумноженных значений, просто поделите на Da, результирующий альфа.

1 голос
/ 10 декабря 2016

Я нашел этот ответ полезным, и, похоже, он работает, как и ожидалось, при применении той же формулы к альфа-каналу.

Изменено здесь, чтобы показать расширенную версию:

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;
}

Это хорошо работает для быстрого и грязного кода, но есть и более быстрые подходы, как указано в ответе выше, но также рассматриваются здесь и здесь .

0 голосов
/ 12 ноября 2009

Большинство формул смешивания используются на статических изображениях, где целевые цвета альфа не сохраняются. Если альфа доступна, тогда конечной альфой будет просто среднее арифметическое исходной альфы и конечной альфы.

Вы можете рассчитать среднее значение альфа, а затем просто использовать его вместо «Sa» в своей формуле.

Разум говорит нам, для чего это?

...