Я проголосовал за ответ Йоханнеса, потому что он прав в этом.
* Было высказано несколько комментариев о том, что мой первоначальный ответ был неверным. Это работало, если значения альфа были инвертированы от нормального. Однако по определению это не сработает в большинстве случаев. Поэтому я обновил приведенную ниже формулу, чтобы она соответствовала обычному случаю. В итоге получается, что ответ @ hkurabko ниже *
Более конкретный ответ, однако, включает альфа-значение в фактический цветовой результат, основанный на непрозрачном цвете фона (или «матовом», как его называют).
Для этого существует алгоритм (из этой ссылки на википедию):
- Нормализуйте значения RGBA так, чтобы они все были между 0 и 1 - просто разделите каждое значение на 255, чтобы сделать это. Мы назовем результат
Source
.
- Нормализовать также матовый цвет (черный, белый, любой). Мы назовем результат
BGColor
Примечание - если цвет фона также прозрачен, вам придется сначала повторить процесс для этого (опять же, выбирая подложку), чтобы получить исходный RGB для эта операция.
Теперь преобразование определяется как (в полном коде псевдо здесь!):
Source => Target = (BGColor + Source) =
Target.R = ((1 - Source.A) * BGColor.R) + (Source.A * Source.R)
Target.G = ((1 - Source.A) * BGColor.G) + (Source.A * Source.G)
Target.B = ((1 - Source.A) * BGColor.B) + (Source.A * Source.B)
Чтобы получить окончательные значения 0-255 для Target
, просто умножьте все нормализованные значения обратно на 255, убедившись, что вы превысили 255, если какое-либо из комбинированных значений превысит 1,0 (это чрезмерная экспозиция и есть более сложные алгоритмы, связанные с этим, которые включают обработку всего изображения и т. д.).
РЕДАКТИРОВАТЬ: В своем вопросе вы сказали, что хотите белый фон - в этом случае просто установите BGColor на 255,255,255.