Конвертировать цвета RGBA в RGB - PullRequest
70 голосов
/ 12 января 2010

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

Edit:

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

Ответы [ 6 ]

84 голосов
/ 12 января 2010

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

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

36 голосов
/ 15 апреля 2010

хм ... относительно

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

4 голосов
/ 12 января 2010

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

3 голосов
/ 17 апреля 2017

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

rgbImage = cv2.cvtColor(npimage, cv2.COLOR_RGBA2RGB)
1 голос
/ 07 апреля 2018

Вот код 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;
}
1 голос
/ 15 февраля 2016

Вот удобная функция 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);
}
...