Преобразование цвета RGBA в RGB
Вопрос
Как преобразовать цветовой кортеж RGBA, например (96, 96, 96, 202), в соответствующий цветовой кортеж RGB?
Редактировать:
Я хочу получить значение RGB, которое наиболее похоже на кортеж RGBA визуально на белом фоне.
Решение
Я проголосовал за ответ Йоханнеса, потому что он прав в этом.
* Было высказано несколько комментариев о том, что мой первоначальный ответ был неправильным.Это работало, если значения альфа были инвертированы по сравнению с нормальными.Однако по определению в большинстве случаев это не сработает.Поэтому я обновил приведенную ниже формулу, чтобы она соответствовала обычному случаю.В конечном итоге это будет равно ответу @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.
Другие советы
хм...относительно
http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending
Решение, предоставленное Андрасом Золтаном, следует немного изменить на:
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)
Эта измененная версия у меня работает нормально, потому что в пред.версия rgba(0,0,0,0) с матовым rgb(ff,ff,ff) будет изменена на rgb(0,0,0).
Это зависит от используемого вами цветового пространства.Если RGBA находится в предварительно умноженном цветовом пространстве и является полупрозрачным, вам необходимо разделить альфу, чтобы получить правильный цвет RGB.Если цвет находится в цветовом пространстве без предварительного умножения, вы можете просто отказаться от альфа-канала.
В моем случае я хотел преобразовать изображение RGBA в RGB, и следующее сработало так, как и ожидалось:
rgbImage = cv2.cvtColor(npimage, cv2.COLOR_RGBA2RGB)
Вот удобная функция SASS в соответствии с ответами Андраса и Хкурабко.
@function rgba_blend($fore, $back) {
$ored: ((1 - alpha($fore)) * red($back) ) + (alpha($fore) * red($fore));
$ogreen: ((1 - alpha($fore)) * green($back) ) + (alpha($fore) * green($fore));
$oblue: ((1 - alpha($fore)) * blue($back) ) + (alpha($fore) * blue($fore));
@return rgb($ored, $ogreen, $oblue);
}
Использование:
$my_color: rgba(red, 0.5); // build a color with alpha for below
#a_div {
background-color: rgba_blend($my_color, white);
}
Вот некоторый Java-код (работает на Android API 24):
//int rgb_background = Color.parseColor("#ffffff"); //white background
//int rgba_color = Color.parseColor("#8a000000"); //textViewColor
int defaultTextViewColor = textView.getTextColors().getDefaultColor();
int argb = defaultTextViewColor;
int alpha = 0xFF & (argb >> 24);
int red = 0xFF & (argb >> 16);
int green = 0xFF & (argb >> 8);
int blue = 0xFF & (argb >> 0);
float alphaFloat = (float)alpha / 255;
String colorStr = rgbaToRGB(255, 255, 255, red, green, blue, alphaFloat);
функция:
protected String rgbaToRGB(int rgb_background_red, int rgb_background_green, int rgb_background_blue,
int rgba_color_red, int rgba_color_green, int rgba_color_blue, float alpha) {
float red = (1 - alpha) * rgb_background_red + alpha * rgba_color_red;
float green = (1 - alpha) * rgb_background_green + alpha * rgba_color_green;
float blue = (1 - alpha) * rgb_background_blue + alpha * rgba_color_blue;
String redStr = Integer.toHexString((int) red);
String greenStr = Integer.toHexString((int) green);
String blueStr = Integer.toHexString((int) blue);
String colorHex = "#" + redStr + greenStr + blueStr;
//return Color.parseColor(colorHex);
return colorHex;
}