Преобразование цвета RGBA в RGB

79

Как преобразовать набор цветов RGBA, например (96, 96, 96, 202), в соответствующий набор цветов RGB?

Редактировать:

Я хочу получить значение RGB, которое больше всего похоже на кортеж RGBA визуально на белом фоне.

Джек
источник
3
Разве это не было бы (96,96,96)?
Lazarus
24
Это зависит от цвета фонового пикселя.
Фрэнк Боллак,
5
Вы просто хотите удалить альфа-канал? Или вам нужен результат RGB наложения RGBA на (например) белый фон?
Бен Джеймс
1
Вы можете прочитать знаменитую статью «Составление цифровых изображений» (Портер и Дафф) для получения полной информации об альфа-композиции: keithp.com/~keithp/porterduff
kusma
Ответ Андраса Золтана и Хкурабко также полезен для расчета противоположного, я имею в виду, что если у вас есть различные цвета с альфа-смешением и исходный фон (матовый), вы можете рассчитать исходный цвет RGBA, который я искал while;)
nacho4d

Ответы:

90

Я поддержал ответ Йоханнеса, потому что он прав в этом.

* Было высказано несколько комментариев о том, что мой первоначальный ответ был неправильным. Это работало, если альфа-значения были инвертированы по сравнению с нормальными. Однако по определению в большинстве случаев это не сработает. Поэтому я обновил приведенную ниже формулу, чтобы она соответствовала нормальному случаю. Это в конечном итоге равно ответу @ hkurabko ниже *

Однако более конкретный ответ включает альфа-значение в фактический результат цвета на основе непрозрачного цвета фона (или «матового», как его называют).

Для этого есть алгоритм (из этой ссылки в википедии):

  • Нормализуйте значения RGBA, чтобы все они находились в диапазоне от 0 до 1 - для этого просто разделите каждое значение на 255. Назовем результатSource .
  • Нормализуйте также матовый цвет (черный, белый или какой угодно). Назовем результат BGColor Note - если цвет фона также является прозрачным, вам придется сначала повторить процесс для этого (опять же, выбрав матовый цвет), чтобы получить исходный 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.

Андраш Золтан
источник
9
В свете редактирования вопроса это очень точный и хороший ответ. Я удалил свой и надеюсь, что вы всплывете, так как вы объяснили суть дела лучше :)
Джоуи,
Я думаю, этот ответ предполагает, что цвет фона - rgb, а не rgba.
Лев,
Это необычно, учитывая, что RGBA (0,0,0,1) полностью непрозрачный черный. Но с данным алгоритмом он был бы полностью прозрачным черным. Я думаю, что изменение алгоритма, чтобы отразить это, сделало бы его более полезным ресурсом и лучшим ответом на вопрос.
Брайан Рейнер
1
@BryanRayner добавил некоторые правки к моему ответу. Я регулярно получаю положительные голоса за этот ответ, и возможно, что некоторые люди находят его, и им приходится самостоятельно инвертировать алгоритм. Лучше бы она была полнее. Благодарю.
Андрас Золтан
2
Если кому-то еще интересно, этот JSBin позволяет наблюдать за трансформируемым цветом. Также он готов к использованию в качестве функции javacript. Я использовал BGColor как белый, потому что просто не понимаю концепции матового (извините!). Ссылка выглядит следующим образом: jsbin.com/qocixeh/edit?html,js,console,output, а также суть: gist.github.com/vladimirbrasil/bd139851ff757a1c8cb46fac93e733eb Надеюсь, это тоже поможет. Огромное спасибо за ответ!
Владимир Бразил
40

хм ... что касается

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).

Хкурабко
источник
Я считаю, что вы правы. Википедия и ответ Андраса Золтана немного отличаются.
nacho4d
1
Я согласен, используйте эту версию, а не версию @Andras Zoltan. Для тестового сценария конвертируйте rgba (0,0,0, .7) в фоновый rgb (255,255,255), используя обе формулы; Форумла хкурабко явно дает правильный ответ.
Ryre
4
Андрас определяет 0 альфа как непрозрачный и 255 как прозрачный, в то время как CSS определяет это наоборот. Этот ответ работает с определением альфа-канала в CSS.
Кейси Чу,
1
+1 Это работает с наиболее распространенным определением альфа-канала (0 = прозрачный), например, OpenGL, SDL, графические редакторы.
DLight
+1 - и я обновил свой ответ, чтобы работать с альфой, являющейся «правильным путем», согласно этому тоже. По иронии судьбы, просто попытавшись использовать свое решение для этого, я согласен с тем, что мой первоначальный ответ, хотя и имел определенный смысл, на самом деле не работал для большинства приложений.
Андрас Золтан,
8

В моем случае я хотел преобразовать изображение RGBA в RGB, и следующее сработало так, как ожидалось:

rgbImage = cv2.cvtColor(npimage, cv2.COLOR_RGBA2RGB)
Сулабхмателе
источник
5

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

кусма
источник
1

Вот удобная функция 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);
}
Рохантевиз
источник
в sass мы можем использовать:mix($color, white, $alpha*100)
S.Serpooshan
1

Вот код 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;
}
живи любя
источник