Convertir RGB a RGBA sobre blanco
Tengo un color hexadecimal, por ejemplo #F4F8FB
(o rgb(244, 248, 251)
) que quiero convertir en un color lo más transparente posible (cuando se muestra sobre blanco). ¿Tener sentido? Estoy buscando un algoritmo, o al menos una idea de un algoritmo sobre cómo hacerlo.
Por ejemplo:
rgb( 128, 128, 255 ) --> rgba( 0, 0, 255, .5 )
rgb( 152, 177, 202 ) --> rgba( 50, 100, 150, .5 ) // can be better(lower alpha)
¿Ideas?
Solución para su información basada en la respuesta de Guffa:
function RGBtoRGBA(r, g, b){
if((g == null) && (typeof r === 'string')){
var hex = r.replace(/^\s*#|\s*$/g, '');
if(hex.length === 3){
hex = hex.replace(/(.)/g, '$1$1');
}
r = parseInt(hex.substr(0, 2), 16);
g = parseInt(hex.substr(2, 2), 16);
b = parseInt(hex.substr(4, 2), 16);
}
var min, a = (255 - (min = Math.min(r, g, b))) / 255;
return {
r : r = 0|(r - min) / a,
g : g = 0|(g - min) / a,
b : b = 0|(b - min) / a,
a : a = (0|1000*a)/1000,
rgba : 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')'
};
}
RGBtoRGBA(204, 153, 102) == RGBtoRGBA('#CC9966') == RGBtoRGBA('C96') ==
{
r : 170,
g : 85 ,
b : 0 ,
a : 0.6,
rgba : 'rgba(170, 85, 0, 0.6)'
}
Tome el componente de color más bajo y conviértalo a un valor alfa. Luego escale los componentes de color restando el más bajo y dividiéndolo por el valor alfa.
Ejemplo:
152 converts to an alpha value of (255 - 152) / 255 ~ 0.404
152 scales using (152 - 152) / 0.404 = 0
177 scales using (177 - 152) / 0.404 ~ 62
202 scales using (202 - 152) / 0.404 ~ 123
Entonces, rgb(152, 177, 202)
se muestra como rgba(0, 62, 123, .404)
.
He verificado en Photoshop que los colores realmente combinan perfectamente.
Sean r, g y b los valores de entrada y r', g', b' y a' los valores de salida, todos escalados (por ahora, ya que hace las matemáticas más bonitas) entre 1 y 0. Luego, por la fórmula para superponer colores:
r = a' * r' + 1 - a'
g = a' * g' + 1 - a'
b = a' * b' + 1 - a'
Los términos 1 - a' representan la contribución de fondo y los demás términos representan el primer plano. Haz algo de álgebra:
r = a' * (r' - 1) + 1
r - 1 = a' * (r' - 1)
(r - 1) / (r' - 1) = a'
(r' - 1) / (r - 1) = 1 / a'
r' - 1 = (r - 1) / a'
r' = (r - 1) / a' + 1
Intuitivamente, parece que el valor mínimo de color será el factor limitante en el problema, así que vincule esto a m:
m = min(r, g, b)
Establezca el valor de salida correspondiente, m', en cero, ya que queremos maximizar la transparencia:
0 = (m - 1) / a' + 1
-1 = (m - 1) / a'
-a' = m - 1
a' = 1 - m
Entonces, en javascript (traduciendo del 1 al 255 en el camino):
function rgba(r, g, b) {
var a = 1 - Math.min(r, Math.min(g, b)) / 255;
return [255 + (r - 255) / a, 255 + (g - 255) / a, 255 + (b - 255) / a, a];
}
Tenga en cuenta que asumo que a' es opacidad aquí. Es trivial cambiarlo a transparencia; simplemente elimine el "1 -" de la fórmula para a'. Algo a tener en cuenta es que esto no parece producir resultados exactos: decía que la opacidad era 0,498 para el ejemplo que proporcionó anteriormente (128, 128, 255). Sin embargo, esto está muy cerca.
Buscaría la conversión RGB<->HSL. Es decir, luminosidad == cantidad de blanco == cantidad de transparencia.
Para su ejemplo rgb( 128, 128, 255 )
, necesitamos cambiar los valores RGB al 0
primero en la cantidad máxima, es decir rgb( 0, 0, 128 )
, ese sería nuestro color con la menor cantidad de blanco posible. Y después de eso, usando la fórmula para la luminancia, calculamos la cantidad de blanco que necesitamos agregar a nuestro color oscuro para obtener el color original; ese sería nuestro alfa:
L = (MAX(R,G,B) + MIN(R,G,B))/2
L1 = (255 + 128) / 2 = 191.5
L2 = (128 + 0) /2 = 64
A = (191,5 - 64) / 255 = 0,5;
Espero que tenga sentido. :)