在Android中使用颜色和color.darker?

好的,所以我在我的应用程序中有一个整数variables。 这是一个颜色的价值,由我的喜好中的颜色select器设置。 现在,我需要使用这种颜色和任何颜色的黑色版本。

现在我知道在标准Java中有一个Color.darker()方法,但在Android中似乎没有相同的地方。 有谁知道一个等效或任何解决方法?

我认为最简单的办法就是转换成HSV,在那里变暗,然后转换回来:

float[] hsv = new float[3]; int color = getColor(); Color.colorToHSV(color, hsv); hsv[2] *= 0.8f; // value component color = Color.HSVToColor(hsv); 

为了减轻压力,一个简单的方法可能是将值分量乘以> 1.0。 但是,您必须将结果限制在[0.0,1.0]范围内。 而且,单纯的乘法不会减轻黑色。

因此,更好的解决scheme是:减less从1.0的价值组件的差异减轻:

 hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]); 

这与暗化方法完全平行,只使用1作为原点而不是0.它可以减轻任何颜色(甚至是黑色)并且不需要任何夹紧。 它可以简化为:

 hsv[2] = 0.2f + 0.8f * hsv[2]; 

但是,由于浮点运算的四舍五入效应,我担心结果可能会超过1.0f(大概是一位)。 更好地坚持稍微复杂的公式。

这是我创build的:

 /** * 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 ) ); } 

泰德的减轻颜色的答案不适合我,所以这里有一个解决scheme可以帮助别人:

 /** * 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); } 

用于变暗和变亮的Java Color例程不需要任何特殊的东西。 实际上,这只不过是展开对相关颜色亮度的理解。 也就是说,你可以简单地采取红色,绿色,蓝色的价值观。 将它们乘以任何因素,确保它们正确地转化为色域。

以下是在Color类中find的代码。

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

显然,从这里我们可以看到如何在android中做这个过程。 取RGB值,乘以一个因子,然后将它们压缩成色域。 (由于许可原因重新编号)。

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

请注意,这与增加HSB的亮度是一样的,B是最亮的因素,色调是各种颜色之间的比例,S是它们之间的距离。 所以如果我们只是抓住所有的颜色并把它们乘以一个因子,我们就会在同一个混合中得到相同的颜色,而在它们之间会有更多的白色/黑色。

许多现代色彩空间也通过各种最接近亮度的色彩分量来计算Y值。 所以,如果你想通过任何现代色彩空间转换成更好的Y或Lforms,并且不转换它们,那么其他色彩空间对于每种颜色对实际亮度,亮度,白度,黑度,或任何色彩空间所谓的。 这会做得更好,但是对于大多数情况来说,这是可靠的。

所以在最极端的情况下,您可以通过转换为Lab来减lessL分量并将其转换回来。

这里是代码来做到这一点:

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

我的几条线和Color.darken()是一样的,这里是一个样本颜色集的图像(这些颜色是通过CIE-LabD2000与以前所有颜色的最大距离,只是将它们用作一个强大的颜色样本集。

索引颜色,Color.darker()和我的基本darken(),都在0.7的因子。 指数与黑暗与黑暗 (这些应该是相同的)

接下来对于那些build议使用实验室变黑的人来说,

索引颜色,Color.darker()和Lab Darker(),全部在FACTOR为0.7。 在这里输入图像说明 (这是一个值得浪费时间的改进吗?)

 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { getWindow().setStatusBarColor(CircleView.shiftColorDown(color)); }// color is 'int' value