135

我正在尝试评估颜色选择器选择的颜色的暗度,以查看它是否“太黑”,如果是,请将其设置为白色。我想我可以使用十六进制值的第一个字符来解决这个问题。它正在工作,但它也在切换一些合法的“浅色”颜色。

我有这样做的代码:

        if (lightcolor.substring(0,3) == "#00"|| lightcolor.substring(0,3) == "#010"){
            lightcolor="#FFFFFF";
            color=lightcolor;
        }

必须有一种更有效的十六进制数学方法来知道颜色已经超过了一定程度的黑暗?就像如果 lightcolor + "some hex value" <= "some hex value" 然后将其设置为白色。

我添加了 tinyColor,它可能对此有用,但我不确定。

4

8 回答 8

259

您必须分别提取三个 RGB 分量,然后使用标准公式将生成的 RGB 值转换为它们的感知亮度。

假设有六个字符的颜色:

var c = c.substring(1);      // strip #
var rgb = parseInt(c, 16);   // convert rrggbb to decimal
var r = (rgb >> 16) & 0xff;  // extract red
var g = (rgb >>  8) & 0xff;  // extract green
var b = (rgb >>  0) & 0xff;  // extract blue

var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709

if (luma < 40) {
    // pick a different colour
}

编辑

自 2014 年 5 月以来,tinycolor现在有了一项getBrightness()功能,尽管使用的是 CCIR601 加权因子而不是上面的 ITU-R 加权因子。

编辑

生成的亮度值范围是 0..255,其中 0 是最暗的,255 是最亮的。大于 128 的值被 认为是轻的tinycolor。(无耻地抄袭@pau.moreno 和@Alnitak 的评论)

于 2012-08-20T18:42:20.667 回答
38

我找到了这个 WooCommerce Wordpress PHP 函数 ( wc_hex_is_light ) 并转换为 JavaScript。工作正常!

function wc_hex_is_light(color) {
    const hex = color.replace('#', '');
    const c_r = parseInt(hex.substr(0, 2), 16);
    const c_g = parseInt(hex.substr(2, 2), 16);
    const c_b = parseInt(hex.substr(4, 2), 16);
    const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
    return brightness > 155;
}
于 2018-07-28T02:36:40.917 回答
30

TinyColor库(您已经提到过)提供了几个用于检查和操作颜色的函数,其中包括

于 2015-09-07T15:32:56.117 回答
6

您可以计算亮度

因此,亮度是表面看起来有多亮的指标。

因此,最好选择文本应该是白色还是黑色。

var getRGB = function(b){
    var a;
    if(b&&b.constructor==Array&&b.length==3)return b;
    if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])];
    if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];
    if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],
16)];
    if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];
    return (typeof (colors) != "undefined")?colors[jQuery.trim(b).toLowerCase()]:null
};

var luminance_get = function(color) {
    var rgb = getRGB(color);
    if (!rgb) return null;
        return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
}

上面的方法可以让你传递不同格式的颜色,但算法基本上只是在luminance_get.

当我使用它时,如果亮度大于 ,我将颜色设置为黑色180,否则设置为白色。

于 2012-08-20T18:43:43.213 回答
6

这与十六进制一起工作,例如#fefefe

function isTooDark(hexcolor){
    var r = parseInt(hexcolor.substr(1,2),16);
    var g = parseInt(hexcolor.substr(3,2),16);
    var b = parseInt(hexcolor.substr(4,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;
    // Return new color if to dark, else return the original
    return (yiq < 40) ? '#2980b9' : hexcolor;
}

您可以将其更改为返回truefalse更改

return (yiq < 40) ? '#2980b9' : hexcolor;

return (yiq < 40);
于 2017-09-11T08:50:27.970 回答
5

亮度和亮度之间有一个重要的区别。归根结底,亮度是衡量有多少能量穿过某个区域的量度,完全忽略了我们的感知系统如何感知该能量。另一方面,亮度是衡量我们如何感知能量的量度,并考虑了亮度与我们的感知系统之间的关系。(作为一个混淆点,有一个术语称为相对亮度,它似乎与亮度术语同义。它让我很受挫)。

准确地说,您正在寻找其他人建议的“亮度”或“价值”或“相对亮度”。你可以用几种不同的方式来计算(这就是人类!)http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness

  1. 取 R、G 和 B 的最大值。
  2. 取 R、G 和 B 的最大值和最小值的平均值。
  3. 取三者的平均值。
  4. 正如其他人在这里建议的那样,使用一些加权平均值。
于 2012-08-20T19:13:49.863 回答
2

一种可能的解决方案是将您的颜色从 RGB 转换为 HSB。HSB 代表色调、饱和度和亮度(也称为 HSV,其中 V 代表值)。然后你只需要检查一个参数:亮度。

于 2012-08-20T18:43:05.860 回答
2

我意识到这个对话已经有几年的历史了,但它仍然是相关的。我想补充一点,我的团队在 Java (SWT) 中遇到了同样的问题,发现这更准确一点:

private Color getFontColor(RGB bgColor) {
    Color COLOR_BLACK = new Color(Display.getDefault(), 0, 0, 0);
    Color COLOR_WHITE = new Color(Display.getDefault(), 255, 255, 255);

    double luminance = Math.sqrt(0.241 
       * Math.pow(bgColor.red, 2) + 0.691 * Math.pow(bgColor.green, 2) +  0.068 
       * Math.pow(bgColor.blue, 2));
    if (luminance >= 130) {
        return COLOR_BLACK;
    } else {
        return COLOR_WHITE;
    }
}
于 2017-04-20T13:40:45.640 回答