Convierta el color RGBA a RGB

79

¿Cómo convertir una tupla de color RGBA, por ejemplo (96, 96, 96, 202), a la tupla de color RGB correspondiente?

Editar:

Lo que quiero es obtener un valor RGB que sea más similar a la tupla RGBA visualmente sobre fondo blanco.

Jack
fuente
3
¿No sería eso (96,96,96)?
Lázaro
24
Eso depende del color del píxel de fondo.
Frank Bollack
5
¿Solo quieres eliminar el canal alfa? ¿O desea el resultado RGB de superponer el RGBA sobre un (por ejemplo) fondo blanco?
Ben James
1
Es posible que desee leer el famoso artículo "Composición de imágenes digitales" (de Porter y Duff) para obtener detalles completos sobre la composición alfa: keithp.com/~keithp/porterduff
kusma
La respuesta de Andras Zoltan y hkurabko también son útiles para calcular el opuesto, quiero decir, si tiene varios colores mezclados alfa y tiene sus fondos originales (mates), entonces podría calcular el color RGBA original, que es lo que he estado buscando. while;)
nacho4d

Respuestas:

90

He votado a favor de la respuesta de Johannes porque tiene razón en eso.

* Se han hecho algunos comentarios de que mi respuesta original no era correcta. Funcionó si los valores alfa se invirtieran de lo normal. Sin embargo, por definición, esto no funcionará en la mayoría de los casos. Por lo tanto, actualicé la fórmula a continuación para que sea correcta para el caso normal. Esto termina siendo igual a la respuesta de @ hkurabko a continuación *

Sin embargo, una respuesta más específica incorpora el valor alfa en el resultado de color real basado en un color de fondo opaco (o 'mate' como se le conoce).

Hay un algoritmo para esto (de este enlace de wikipedia):

  • Normalice los valores RGBA para que estén todos entre 0 y 1; simplemente divida cada valor por 255 para hacer esto. Llamaremos al resultado Source.
  • Normaliza también el color mate (negro, blanco lo que sea). Llamaremos al resultado BGColor Nota : si el color de fondo también es transparente, primero tendrá que repetir el proceso (nuevamente, eligiendo un mate) para obtener el RGB de origen para esta operación.
  • Ahora, la conversión se define como (¡en código psuedo completo aquí!):

    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)
    

Para obtener los valores finales de 0-255 Target, simplemente multiplique todos los valores normalizados de nuevo por 255, asegurándose de limitar a 255 si alguno de los valores combinados excede 1.0 (esto es sobreexposición y hay algoritmos más complejos que se ocupan de esto que involucran procesamiento de imagen completa, etc.).

EDITAR: En su pregunta, dijo que desea un fondo blanco; en ese caso, simplemente fije BGColor en 255,255,255.

Andras Zoltan
fuente
9
A la luz de la edición de la pregunta, esta es una respuesta muy precisa y buena. He eliminado la mía y espero que brotan, ya que explicó mejor manera los asuntos :)
Joey
Creo que esta respuesta asume que el color de fondo es rgb, no rgba.
Leo
Esto es inusual considerando que RGBA (0,0,0,1) es negro completamente opaco. Pero con el algoritmo dado, sería completamente negro transparente. Creo que reorganizar el algoritmo para reflejar esto lo convertiría en un recurso más útil y una mejor respuesta a la pregunta.
Bryan Rayner
1
@BryanRayner ha agregado algunas modificaciones a mi respuesta. Estoy obteniendo votos positivos por esta respuesta con regularidad, y es posible que algunas personas la encuentren y tengan que invertir el algoritmo ellos mismos. Sería mejor si fuera más completo. Gracias.
Andras Zoltan
2
Si alguien todavía está interesado, este JSBin permite ver cómo se transforma el color. También está listo para usarse como función javacript. Usé BGColor como blanco, porque simplemente no entiendo el concepto mate (¡lo siento!). El enlace es el siguiente: jsbin.com/qocixeh/edit?html,js,console,output y también una esencia: gist.github.com/vladimirbrasil/bd139851ff757a1c8cb46fac93e733eb Espero que también ayude. ¡Un trillón de gracias por la respuesta!
Vladimir Brasil
40

hm ... con respecto a

http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending

La solución proporcionada por Andras Zoltan debe cambiarse ligeramente a:

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)

Esta versión modificada funciona bien para mí, porque en la anterior. la versión rgba (0,0,0,0) con matte rgb (ff, ff, ff) se cambiará a rgb (0,0,0).

hkurabko
fuente
Creo que tienes razón. La respuesta de Wikipedia y Andras Zoltan es un poco diferente.
nacho4d
1
Estoy de acuerdo, use esta versión, no la de @Andras Zoltan. Para un escenario de prueba, convierta rgba (0,0,0, .7) en rgb de fondo (255,255,255) usando ambas fórmulas; La forumala de hkurabko produce claramente la respuesta correcta.
Ryre
4
Andras define 0 alfa como opaco y 255 como transparente, mientras que CSS lo define al revés. Esta respuesta funciona con la definición de alfa de CSS.
Casey Chu
1
+1 Esto funciona con la definición más común de alfa (0 = transparente) como OpenGL, SDL, editores gráficos.
Dight
+1 - y he actualizado mi respuesta para que funcione con alfa como el 'camino correcto', según esto también. Irónicamente, después de haber intentado usar mi solución para hacer esto, estoy de acuerdo en que mi respuesta original, aunque tenía su propio sentido, realmente no funcionó para la mayoría de las aplicaciones.
Andras Zoltan
8

En mi caso, quería convertir una imagen RGBA a RGB y lo siguiente funcionó como se esperaba:

rgbImage = cv2.cvtColor(npimage, cv2.COLOR_RGBA2RGB)
SulabhMatele
fuente
5

Esto depende del espacio de color que utilice. Si el RGBA está en un espacio de color pre-multiplicado y es semitransparente, debe dividir alfa para obtener el color RGB correcto. Si el color está en un espacio de color no pre-multiplicado, puede descartar el canal alfa.

kusma
fuente
1

Aquí hay una función SASS conveniente de acuerdo con las respuestas de Andras y hkurabko.

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

Uso:

$my_color: rgba(red, 0.5); // build a color with alpha for below

#a_div {
  background-color: rgba_blend($my_color, white);
}
Rohanthewiz
fuente
con descaro, podemos usar:mix($color, white, $alpha*100)
S.Serpooshan
1

Aquí hay un código de Java (funciona en 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);

función:

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;
}
vive el amor
fuente