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

Java 在Android中使用颜色和color.darker?,java,android,colors,Java,Android,Colors,好的,我的应用程序中有一个整数变量。它是一种颜色的值,由我的首选项中的颜色选择器设置。现在,我需要同时使用这种颜色和任何颜色的深色版本 现在我知道在标准Java中有一个Color.darker()方法,但在Android中似乎没有类似的方法。有人知道类似的或任何解决方法吗?我认为,最简单的方法是转换为HSV,在那里进行变暗,然后转换回: float[] hsv = new float[3]; int color = getColor(); Color.colorToHSV(color, hsv)

好的,我的应用程序中有一个整数变量。它是一种颜色的值,由我的首选项中的颜色选择器设置。现在,我需要同时使用这种颜色和任何颜色的深色版本


现在我知道在标准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]。而且,简单的乘法并不能使黑色变亮

因此,更好的解决方案是:将值分量的差值从1.0减小到更轻:

hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]);
这与变暗的方法完全相同,只是使用1作为原点,而不是0。它的作品,以减轻任何颜色(甚至黑色),不需要任何夹紧。可以简化为:

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

然而,由于浮点运算可能会产生舍入效应,我担心结果可能会超过1.0f(可能超过一位)。最好坚持使用稍微复杂一点的公式。

以下是我创建的:

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

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

用于变暗和变亮的Java颜色例程不需要任何特殊的东西。事实上,这只是对亮度应用于相关颜色的展开理解。也就是说,你可以简单地取红色,绿色,蓝色的值。将它们乘以任何因子,确保它们正确地进入色域

以下是颜色类中的代码。

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值,乘以一个因子,然后将它们卷曲成色域。(出于许可原因从头开始重新编码)

公共内部压接(内部c){
返回Math.min(Math.max(c,0),255);
}
公共整数变暗(整数颜色){
双因子=0.7;
返回(颜色&0xFF000000)|

(卷曲((内部)((颜色>>16)和0xFF)*系数))>8)&0xFF)*factor)我很好奇我的建议怎么会对您不利。您能提供详细信息吗?我发现某些颜色的这种效果在视觉上比其他颜色强得多。因此,它对我不是很有用。@ABoschman-这是一个有趣的观点。您可能会通过转换和进行照明获得更好的效果/通过将我的答案中的技术应用于亮度组件,使其变暗。不幸的是,RGB和lab颜色空间之间的转换并不简单(如本文所述),您必须滚动您自己的转换代码。lab颜色空间的优势在于(如文中所述)它比其他空间更能模拟人类的颜色感知。@TedHopp改变HSL而不是HSV难道没有意义吗?人们可以使用android.support.v4.graphics.ColorUtils#RGBToHSL()。@MartinRajniak-我不认为两者有任何优势。例如,请参阅或维基百科文章。我收回——a(非常轻微)HSV的优点是它不依赖于支持库(以防其他原因不需要它)。回答很好,有助于颜色的变暗和变亮。我只想补充一点,您还可以操纵
HSV[1]
参数来获得“亮度”在颜色方面,我个人希望采用这种方法得到一种柔和/褪色的颜色,如果你想让颜色暗10%,那么你需要加入(1-因子)=>(1-0.1f)=>0.9f
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)));
    }
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;
}