La rutina Java Color para oscurecer y aclarar no requiere nada especial. De hecho, es simplemente la comprensión desenrollada de qué brillo se aplica a los colores relevantes. Lo que quiere decir que simplemente puede tomar los valores rojo, verde, azul. Multiplíquelos por cualquier factor, asegúrese de que caigan correctamente en la gama.
El siguiente es el código que se encuentra en la clase Color.
private static final double FACTOR = 0.7;
//...
public Color darker() {
return new Color(Math.max((int)(getRed() *FACTOR), 0),
Math.max((int)(getGreen()*FACTOR), 0),
Math.max((int)(getBlue() *FACTOR), 0),
getAlpha());
}
Obviamente, a partir de esto podemos ver cómo se hace este proceso en androide. Tome los valores RGB, multiplíquelos por un factor y críjelos en la gama. (Recodificado desde cero por razones de licencia).
public int crimp(int c) {
return Math.min(Math.max(c, 0), 255);
}
public int darken(int color) {
double factor = 0.7;
return (color & 0xFF000000) |
(crimp((int) (((color >> 16) & 0xFF) * factor)) << 16) |
(crimp((int) (((color >> 8) & 0xFF) * factor)) << 8) |
(crimp((int) (((color) & 0xFF) * factor)));
}
hacer la nota que esto es lo mismo que simplemente aumentando el brillo en HSB, el B es simplemente el factor más brillante, el tono es la relación entre los diversos colores, y S es lo lejos que están. Entonces, si simplemente tomamos todos los colores y los multiplicamos por un factor, terminamos con los mismos colores en la misma mezcla con un poco más de blanco/negro en ellos.
Muchos espacios de colores modernos también hacen esto al calcular el valor Y a través de los diversos componentes de color que mejor se aproximan al brillo.Por lo que podría si quisiera convertir a una mejor forma de Y o L a través de cualquiera de los espacios de colores modernos y unconvert ellos, otros espacios de color tienen una mejor forma de gamma con respecto a la cantidad de cada color contribuye a la luminosidad real, ligereza, el valor, blancura, negrura, o lo que sea que el espacio de color lo llame. Esto haría un mejor trabajo, pero para la mayoría de los propósitos, esto es sólido.
Así, en el extremo más-usted puede hacer esto mediante la conversión de laboratorio, disminuyendo el componente L y convertir de nuevo.
Aquí está el código para hacer eso:
static int darken(int color) {
double factor = 0.7;
double[] returnarray = new double[3];
convertRGBsRGB(returnarray, ((color >> 16) & 0xFF), ((color >> 8) & 0xFF), (color & 0xFF));
convertRGBXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]);
convertXYZLab(returnarray,returnarray[0], returnarray[1], returnarray[2]);
returnarray[0] *= factor;
convertLabXYZ(returnarray,returnarray[0], returnarray[1], returnarray[2]);
convertXYZRGB(returnarray,returnarray[0], returnarray[1], returnarray[2]);
return (color & 0xFF000000) | convertsRGBRGB(returnarray);
}
static void convertRGBsRGB(double[] returnarray, int R, int G, int B) {
double var_R = (((double) R)/255.0d); //RGB from 0 to 255
double var_G = (((double) G)/255.0d);
double var_B = (((double) B)/255.0d);
returnarray[0] = var_R;
returnarray[1] = var_G;
returnarray[2] = var_B;
}
static int convertsRGBRGB(double[] sRGB) {
int red = (int) (sRGB[0] * 255);
int green = (int) (sRGB[1] * 255);
int blue = (int) (sRGB[2] * 255);
red = crimp(red);
green = crimp(green);
blue = crimp(blue);
return (red << 16) | (green << 8) | blue;
}
public static int crimp(int v) {
if (v > 0xff) {
v = 0xff;
}
if (v < 0) {
v = 0;
}
return v;
}
public static final double ref_X = 95.047; //ref_X = 95.047 Observer= 2°, Illuminant= D65
public static final double ref_Y = 100.000; //ref_Y = 100.000
public static final double ref_Z = 108.883;//ref_Z = 108.883
static void convertRGBXYZ(double[] returnarray, double var_R, double var_G, double var_B) {
if (var_R > 0.04045) {
var_R = Math.pow(((var_R + 0.055)/1.055), 2.4);
} else {
var_R = var_R/12.92;
}
if (var_G > 0.04045) {
var_G = Math.pow(((var_G + 0.055)/1.055), 2.4);
} else {
var_G = var_G/12.92;
}
if (var_B > 0.04045) {
var_B = Math.pow(((var_B + 0.055)/1.055), 2.4);
} else {
var_B = var_B/12.92;
}
var_R = var_R * 100;
var_G = var_G * 100;
var_B = var_B * 100; //Observer. = 2°, Illuminant = D65
double X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
double Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
double Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
returnarray[0] = X;
returnarray[1] = Y;
returnarray[2] = Z;
}
static void convertXYZLab(double[] returnarray, double X, double Y, double Z) {
double var_X = X/ref_X;
double var_Y = Y/ref_Y;
double var_Z = Z/ref_Z;
if (var_X > 0.008856) {
var_X = Math.cbrt(var_X);
} else {
var_X = (7.787 * var_X) + (16.0d/116.0d);
}
if (var_Y > 0.008856) {
var_Y = Math.cbrt(var_Y);
} else {
var_Y = (7.787 * var_Y) + (16.0d/116.0d);
}
if (var_Z > 0.008856) {
var_Z = Math.cbrt(var_Z);
} else {
var_Z = (7.787 * var_Z) + (16.0d/116.0d);
}
double CIE_L = (116 * var_Y) - 16;
double CIE_a = 500 * (var_X - var_Y);
double CIE_b = 200 * (var_Y - var_Z);
returnarray[0] = CIE_L;
returnarray[1] = CIE_a;
returnarray[2] = CIE_b;
}
static void convertLabXYZ(double[] returnarray, double CIE_L, double CIE_a, double CIE_b) {
double var_Y = (CIE_L + 16)/116;
double var_X = CIE_a/500 + var_Y;
double var_Z = var_Y - CIE_b/200;
if ((var_Y * var_Y * var_Y) > 0.008856) {
var_Y = (var_Y * var_Y * var_Y);
} else {
var_Y = (((var_Y - 16)/116))/7.787;
}
if ((var_X * var_X * var_X) > 0.008856) {
var_X = (var_X * var_X * var_X);
} else {
var_X = ((var_X - 16)/116)/7.787;
}
if ((var_Z * var_Z * var_Z) > 0.008856) {
var_Z = (var_Z * var_Z * var_Z);
} else {
var_Z = ((var_Z - 16)/116)/7.787;
}
double X = ref_X * var_X; //ref_X = 95.047 Observer= 2°, Illuminant= D65
double Y = ref_Y * var_Y; //ref_Y = 100.000
double Z = ref_Z * var_Z; //ref_Z = 108.883
returnarray[0] = X;
returnarray[1] = Y;
returnarray[2] = Z;
}
static void convertXYZRGB(double[] returnarray, double X, double Y, double Z) {
double var_X = X/100; //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
double var_Y = Y/100; //Y from 0 to 100.000
double var_Z = Z/100; //Z from 0 to 108.883
double var_R = (var_X * 3.2406) + (var_Y * -1.5372) + (var_Z * -0.4986);
double var_G = (var_X * -0.9689) + (var_Y * 1.8758) + (var_Z * 0.0415);
double var_B = (var_X * 0.0557) + (var_Y * -0.2040) + (var_Z * 1.0570);
if (var_R > 0.0031308) {
var_R = 1.055 * (Math.pow(var_R, (1f/2.4f))) - 0.055;
} else {
var_R = 12.92 * var_R;
}
if (var_G > 0.0031308) {
var_G = 1.055 * (Math.pow(var_G, (1f/2.4f))) - 0.055;
} else {
var_G = 12.92 * var_G;
}
if (var_B > 0.0031308) {
var_B = 1.055 * (Math.pow(var_B, (1f/2.4f))) - 0.055;
} else {
var_B = 12.92 * var_B;
}
returnarray[0] = var_R;
returnarray[1] = var_G;
returnarray[2] = var_B;
}
Mis par de líneas allí hacen lo mismo que Color.darken() aquí está una imagen de un conjunto color de la muestra (estos colores son distancia máxima de todo colores anteriores a través de CIE-LabD2000, solo utilizándolos como un sólido conjunto de muestras de color.)
Color de índice, Color.darker(), y mi oscurecimiento básico(), todo a un FACTOR de 0.7. (estos deben ser idénticos)
Siguiente para aquellos que sugirió el uso de laboratorio para oscurecer,
Colour Index, Color.darker(), y el laboratorio más oscuro(), todo ello a un factor de 0,7. (¿es esta una mejora que vale la pena el tiempo de succión?)
Me parece que este efecto es visualmente mucho más fuerte en algunos colores que otros. Por lo tanto, no fue muy útil para mí. –
@ABoschman - Ese es un punto interesante. Puede obtener mejores resultados convirtiendo a [lab color space] (http://en.wikipedia.org/wiki/Lab_color_space) y haciendo el aclarado/oscurecimiento allí aplicando la técnica de mi respuesta al componente de luminosidad. Desafortunadamente, las conversiones entre RGB y el espacio de color del laboratorio no son tan simples (como se discute en el artículo) y tendrá que pasar su propio código de conversión. La ventaja del espacio de color de laboratorio es que (como se discute [aquí] (http://en.wikipedia.org/wiki/Color_difference)) modela más de cerca la percepción del color humano que otros espacios. –
@TedHopp ¿No tendría sentido alterar HSL en lugar de HSV? Uno puede usar android.support.v4.graphics.ColorUtils # RGBToHSL(). –