Nic*_*ick 63 java android colors
好的,我的应用程序中有一个整数变量.这是一种颜色的值,由我喜欢的颜色选择器设置.现在,我需要使用它的颜色和任何颜色的深色版本.
现在我知道在标准Java中有一个Color.darker()方法,但在Android中似乎没有相应的东西.有谁知道等效或任何变通方法?
Ted*_*opp 207
我认为最简单的方法是转换为HSV,在那里变暗,然后转换回来:
float[] hsv = new float[3];
int color = getColor();
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // value component
color = Color.HSVToColor(hsv);
Run Code Online (Sandbox Code Playgroud)
为了减轻,一个简单的方法可能是将值组件乘以> 1.0.但是,您必须将结果限制在[0.0,1.0]范围内.而且,简单地乘以不会减轻黑色.
因此,更好的解决方案是:减少1.0值组件的差异以减轻:
hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]);
Run Code Online (Sandbox Code Playgroud)
这与变暗的方法完全平行,仅使用1作为原点而不是0.它可以减轻任何颜色(甚至是黑色)并且不需要任何夹紧.它可以简化为:
hsv[2] = 0.2f + 0.8f * hsv[2];
Run Code Online (Sandbox Code Playgroud)
但是,由于浮点运算可能产生的舍入效应,我担心结果可能超过1.0f(可能是一位).最好坚持稍微复杂的配方.
Sil*_*ria 33
这是我创造的:
/**
* 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 ) );
}
Run Code Online (Sandbox Code Playgroud)
Jar*_*ler 24
Ted的减轻颜色的答案对我不起作用,所以这里有一个可以帮助别人的解决方案:
/**
* 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);
}
Run Code Online (Sandbox Code Playgroud)
变暗和变亮的Java Color例程不需要任何特殊操作.事实上,它仅仅是对相关颜色应用亮度的展开理解.也就是说,您可以简单地采用红色,绿色,蓝色值.将它们乘以任何因子,确保它们正确地落入色域.
以下是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());
}
Run Code Online (Sandbox Code Playgroud)
显然,从这里我们可以看到如何在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)));
}
Run Code Online (Sandbox Code Playgroud)
请注意,这与增加HSB亮度是一回事,B只是最明亮的因素,色调是各种颜色之间的比例,S是它们之间的距离.因此,如果我们只抓取所有颜色并将它们乘以一个因子,我们最终会在相同的混合中使用相同的颜色,其中有更多的白色/黑色.
许多现代色彩空间也通过最佳近似亮度的各种颜色分量计算Y值来实现这一点.因此,如果你想通过任何现代色彩空间转换为更好的Y或L形式并且不转换它们,那么其他色彩空间在每种颜色对实际亮度,亮度,价值的贡献程度方面都有更好的伽玛形式,白度,黑度或颜色空间所称的任何东西.这样做会更好,但对于大多数用途来说,这是可靠的.
因此,在极端情况下,您可以通过转换为Lab,减少L组件并将其转换回来实现此目的.
这是执行此操作的代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
我的情侣线与Color.darken()做同样的事情,这里是一个样本颜色集的图像(这些颜色是通过CIE-LabD2000与所有先前颜色的最大距离,只是将它们用作稳健的颜色样本集.)
索引颜色,Color.darker()和我的基本变暗(),均为0.7的因子.
(这些应该相同)
对于那些建议使用Lab变暗的人,
Index Color,Color.darker()和Lab Darker(),均为0.7的因子.
(这是一个值得吸时的改进吗?)
归档时间: |
|
查看次数: |
25189 次 |
最近记录: |