给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?

我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。


当前回答

iOS Swift 3.0 (UIColor扩展):

func isLight() -> Bool
{
    if let components = self.cgColor.components, let firstComponentValue = components[0], let secondComponentValue = components[1], let thirdComponentValue = components[2] {
        let firstComponent = (firstComponentValue * 299)
        let secondComponent = (secondComponentValue * 587)
        let thirdComponent = (thirdComponentValue * 114)
        let brightness = (firstComponent + secondComponent + thirdComponent) / 1000

        if brightness < 0.5
        {
            return false
        }else{
            return true
        }
    }  

    print("Unable to grab components and determine brightness")
    return nil
}

其他回答

这是一个非常有用的答案。谢谢!

我想分享一个SCSS版本:

@function is-color-light( $color ) {

  // Get the components of the specified color
  $red: red( $color );
  $green: green( $color );
  $blue: blue( $color );

  // Compute the perceptive luminance, keeping
  // in mind that the human eye favors green.
  $l: 1 - ( 0.299 * $red + 0.587 * $green + 0.114 * $blue ) / 255;
  @return ( $l < 0.5 );

}

现在弄清楚如何使用算法来自动创建菜单链接的悬停颜色。浅标题的悬停颜色较深,反之亦然。

我有同样的问题,但我必须在PHP开发它。我用了@Garek的解决方案,我也用了这个答案: 转换十六进制颜色到RGB值在PHP转换十六进制颜色代码到RGB。

所以我要分享它。

我想在给定的背景颜色下使用这个函数,但不总是从“#”开始。

//So it can be used like this way:
$color = calculateColor('#804040');
echo $color;

//or even this way:
$color = calculateColor('D79C44');
echo '<br/>'.$color;

function calculateColor($bgColor){
    //ensure that the color code will not have # in the beginning
    $bgColor = str_replace('#','',$bgColor);
    //now just add it
    $hex = '#'.$bgColor;
    list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
    $color = 1 - ( 0.299 * $r + 0.587 * $g + 0.114 * $b)/255;

    if ($color < 0.5)
        $color = '#000000'; // bright colors - black font
    else
        $color = '#ffffff'; // dark colors - white font

    return $color;
}

我也遇到过类似的问题。我必须找到一种选择对比字体颜色的好方法,以便在色度/热图上显示文本标签。它必须是通用的方法,生成的颜色必须“好看”,这意味着简单地生成互补色并不是一个好的解决方案——有时它会生成奇怪的、非常强烈的颜色,很难观察和阅读。

经过长时间的测试和尝试解决这个问题,我发现最好的解决方案是选择白色字体的“深色”,和黑色字体的“明亮”的颜色。

下面是我在c#中使用的一个函数示例:

Color ContrastColor(Color color)
{
    int d = 0;
    
    // Counting the perceptive luminance - human eye favors green color...      
    double luminance = (0.299 * color.R + 0.587 * color.G + 0.114 * color.B)/255;
    
    if (luminance > 0.5)
       d = 0; // bright colors - black font
    else
       d = 255; // dark colors - white font
                
    return  Color.FromArgb(d, d, d);
}

这种方法在许多不同的颜色尺度(彩虹,灰度,热,冰,和许多其他)下进行了测试,这是我发现的唯一“通用”方法。

编辑 改变计算a的公式为“感知亮度”-它真的看起来更好!已经在我的软件中实现了,看起来很棒。

编辑2 @WebSeed提供了这个算法的一个很好的工作示例:http://codepen.io/WebSeed/full/pvgqEq/

Swift 4示例:

extension UIColor {

    var isLight: Bool {
        let components = cgColor.components

        let firstComponent = ((components?[0]) ?? 0) * 299
        let secondComponent = ((components?[1]) ?? 0) * 587
        let thirdComponent = ((components?[2]) ?? 0) * 114
        let brightness = (firstComponent + secondComponent + thirdComponent) / 1000

        return !(brightness < 0.6)
    }

}

更新-发现0.6是一个更好的查询测试平台

谢谢@Gacek。下面是一个Android版本:

@ColorInt
public static int getContrastColor(@ColorInt int color) {
    // Counting the perceptive luminance - human eye favors green color...
    double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;

    int d;
    if (a < 0.5) {
        d = 0; // bright colors - black font
    } else {
        d = 255; // dark colors - white font
    }

    return Color.rgb(d, d, d);
}

还有一个改进的(更短的)版本:

@ColorInt
public static int getContrastColor(@ColorInt int color) {
    // Counting the perceptive luminance - human eye favors green color...
    double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
    return a < 0.5 ? Color.BLACK : Color.WHITE;
}