Javascript 如何检查十六进制颜色是否“太黑”?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12043187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:58:14  来源:igfitidea点击:

How to check if hex color is "too black"?

javascriptcolors

提问by Dshiz

I'm trying to evaluate the darkness of a color chosen by a color picker to see if it's "too black", and if so, set it to white. I thought I could use the first characters of the hex value to pull this off. It's working, but it's switching some legitimately "light" colors too.

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

I have code doing this:

我有这样做的代码:

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

There must be a more efficient way with hex math to know that a color has gone beyond a certain level of darkness? Like if lightcolor + "some hex value" <= "some hex value" then set it to white.

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

I have tinyColor added, which might be of use for this, but I don't know for sure.

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

回答by Alnitak

You have to extract the three RGB components individually, and then use a standard formula to convert the resulting RGB values into their perceived brightness.

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

Assuming a six character colour:

假设一个六个字符的颜色:

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
}

EDIT

编辑

Since May 2014 tinycolornow has a getBrightness()function, albeit using the CCIR601 weighting factors instead of the ITU-R ones above.

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

EDIT

编辑

The resulting luma value range is 0..255, where 0 is the darkest and 255 is the lightest. Values greater than 128 are considered light by tinycolor. (shamelessly copied from the comments by @pau.moreno and @Alnitak)

产生的亮度值范围是 0..255,其中 0 是最暗的,255 是最亮的。大于 128 的值被认为是轻量级的tinycolor。(无耻地从@pau.moreno 和@Alnitak 的评论中复制过来)

回答by skalee

The TinyColorlibrary (you've already mentioned it) provides several functions for inspecting and manipulating colors, among them:

TinyColor库(你已经提到它)提供了用于检查和操纵的色彩,其中几个功能:

回答by Sergio Cabral

I found this WooCommerce Wordpress PHP function (wc_hex_is_light) and I converted to JavaScript. Works fine!

我找到了这个 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;
}

回答by Robin

You can compute the luminance:

您可以计算亮度

Luminance is thus an indicator of how bright the surface will appear.

因此,亮度是表面将出现的亮度的指标。

So it's great to choose if the text should be white or black.

所以最好选择文本应该是白色还是黑色。

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

The method above allows you to pass the color in different formats, but the algorithm is basically just in luminance_get.

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

When I used it, I was setting the color to black if the luminance was greater than 180, white otherwise.

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

回答by David Nguyen

There's an important distinction here between luminance and brightness. Luminance, at the end of the day, is a measure of how much energy travels through a certain area and completely ignores how our perceptual systems perceive that energy. Brightness, on the other hand, is a measure of how we perceive that energy and takes into the account the relationship between luminance and our perceptual system. (As a point of confusion, there is a term called relative luminance, which seems to be used synonymously with brightness terms. It tripped me up good).

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

To be precise, you are looking for "brightness" or "value" or "relatively luminance" as others have suggested. You can calculate this in several different way (such is to be human!) http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness

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

  1. Take the max of R, G, and B.
  2. Take the average of the max and the min from R, G, and B.
  3. Take the average of all three.
  4. Use some weighted average as others have suggested here.
  1. 取 R、G 和 B 的最大值。
  2. 从 R、G 和 B 中取最大值和最小值的平均值。
  3. 取三者的平均值。
  4. 使用一些加权平均值,正如其他人在此处建议的那样。

回答by TheCrazyProfessor

This work with hex e.g #fefefe

这与十六进制一起使用,例如#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;
}


You can change it to return trueor falseby change

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

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

to

return (yiq < 40);

回答by Ohad

A possible solution would be to convert your color from RGB to HSB. HSB stands for hue, saturation, and brightness (also known as HSV, where V is for value). Then you have just one parameter to check: brightness.

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

回答by Chris Clark

I realize this conversation is a few years old, but it is still relevant. I wanted to add that my team was having the same issue in Java (SWT) and found this to be a bit more accurate:

我意识到这段对话已经有几年的历史了,但它仍然具有相关性。我想补充一点,我的团队在 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;
    }
}