java - parsecolor - int color to rgb android
¿Usando color y color.darker en Android? (4)
Aquí está lo que he creado:
/**
* Returns darker version of specified <code>color</code>.
*/
public static int darker (int color, float factor) {
int a = Color.alpha( color );
int r = Color.red( color );
int g = Color.green( color );
int b = Color.blue( color );
return Color.argb( a,
Math.max( (int)(r * factor), 0 ),
Math.max( (int)(g * factor), 0 ),
Math.max( (int)(b * factor), 0 ) );
}
Bien, entonces tengo una variable entera en mi aplicación. Es el valor de un color, establecido por un selector de color en mis preferencias. Ahora, necesito usar tanto ese color como una versión más oscura de cualquier color que pueda ser.
Ahora sé que en Java estándar hay un método Color.darker (), pero no parece haber un equivalente en Android. ¿Alguien sabe de un equivalente o alguna solución?
La respuesta de Ted para aclarar un color no me funcionaba, así que aquí hay una solución que podría ayudar a alguien más:
/**
* Lightens a color by a given factor.
*
* @param color
* The color to lighten
* @param factor
* The factor to lighten the color. 0 will make the color unchanged. 1 will make the
* color white.
* @return lighter version of the specified color.
*/
public static int lighter(int color, float factor) {
int red = (int) ((Color.red(color) * (1 - factor) / 255 + factor) * 255);
int green = (int) ((Color.green(color) * (1 - factor) / 255 + factor) * 255);
int blue = (int) ((Color.blue(color) * (1 - factor) / 255 + factor) * 255);
return Color.argb(Color.alpha(color), red, green, blue);
}
La rutina de 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. Es decir, simplemente puede tomar los valores rojo, verde y azul. Multiplíquelos por cualquier factor, asegúrese de que caigan correctamente en la gama.
El siguiente es el código encontrado en la clase de 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 hacer este proceso en Android. Tome los valores RGB, multiplíquelos por un factor y ajústelos a 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)));
}
Tenga en cuenta que esto es lo mismo que simplemente aumentar el brillo en HSB, la B es simplemente el factor más brillante, el tono es la relación entre los distintos colores y S es la distancia que se encuentran. Entonces, si solo 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 color modernos también hacen esto al calcular el valor de Y a través de los diversos componentes de color que mejor se aproximan al brillo. Entonces, si quisiera convertir a una mejor forma de Y o L a través de cualquiera de los espacios de colores modernos y desconvertirlos, otros espacios de colores tienen una mejor forma de gamma con respecto a cuánto contribuye cada color al brillo, la luminosidad, el valor real. La blancura, la negrura, o como sea que el espacio de colores lo llame. Esto haría un mejor trabajo, pero para la mayoría de los propósitos esto es sólido.
Por lo tanto, en la medida más extrema, puede hacer esto convirtiéndose en Lab, reduciendo el componente L y volviéndolo a convertir.
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 líneas de pareja hacen lo mismo que Color.darken () aquí hay una imagen de un conjunto de colores de muestra (estos colores están a la distancia máxima de todos los colores anteriores a través de CIE-LabD2000, simplemente usándolos como un conjunto de muestras de colores sólidos).
Color de índice, Color.darker () y mi oscurecimiento básico (), todo en un FACTOR de 0.7. (estos deben ser idénticos)
Siguiente para aquellos que sugirieron usar Lab para oscurecer,
Color de índice, Color.darker () y Lab Darker (), todo en un FACTOR de 0.7. (¿Es esta una mejora la pena el tiempo chupar?)
Lo más fácil, creo, sería convertir a HSV, hacer el oscurecimiento allí y volver a convertir:
float[] hsv = new float[3];
int color = getColor();
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // value component
color = Color.HSVToColor(hsv);
Para aclarar, un enfoque simple puede ser multiplicar el componente de valor por algo> 1.0. Sin embargo, tendrá que fijar el resultado al rango [0.0, 1.0]. Además, simplemente multiplicar no va a aclarar el negro.
Por lo tanto, una mejor solución es: Reducir la diferencia de 1.0 del componente de valor para aclarar:
hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]);
Esto es completamente paralelo al enfoque para el oscurecimiento, solo usa 1 como origen en lugar de 0. Funciona para aclarar cualquier color (incluso negro) y no necesita ningún tipo de sujeción. Se podría simplificar a:
hsv[2] = 0.2f + 0.8f * hsv[2];
Sin embargo, debido a los posibles efectos de redondeo de la aritmética de punto flotante, me preocupa que el resultado pueda exceder 1.0f (quizás un bit). Mejor atenerse a la fórmula un poco más complicada.