如何根据字体颜色选择背景颜色以获得适当的对比度

Posted

技术标签:

【中文标题】如何根据字体颜色选择背景颜色以获得适当的对比度【英文标题】:How to pick a background color depending on font color to have proper contrast 【发布时间】:2011-10-09 10:24:31 【问题描述】:

我对颜色组合不太了解,所以我想出了这个算法,它会在试错的基础上根据字体颜色选择背景颜色:

public class BackgroundFromForegroundColorConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    
        if (!(value is Color))
            return value;
        Color color = (Color)value;
        if (color.R + color.G + color.B > 550)
            return new SolidColorBrush(Colors.Gray);
        else if (color.R + color.G + color.B > 400)
            return new SolidColorBrush(Colors.LightGray);
        else
            return new SolidColorBrush(Colors.White);
    

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    
        throw new NotImplementedException();
    

我对此进行了一些谷歌搜索,但我没有发现任何关于计算背景颜色以与字体颜色形成良好对比效果的不同方式的非常正式的内容。

所以我的问题是:是否有更“正式”的方法来选择一个好的背景以获得良好的对比度?或者,您将如何处理选择背景颜色,其唯一目的是让您的文本尽可能易读,无论其字体颜色如何?

快速更新

更多上下文:我只是想显示一些文本的预览(例如“快速棕色狐狸跳过懒狗”),用户可以在其中选择字体颜色、粗细、字体等。我是不管有兴趣看看可以做什么,无论是超级简单还是更复杂。

最终编辑

我决定采用H.B. 的建议:它似乎适用于我尝试过的所有颜色,与我以前的算法不同的是,前景并不总是与背景形成适当的对比。我很想知道是否有公式可以为给定的前景提供“最佳”背景,但对于我需要的黑色/白色效果很好。这是我当前形式的代码:

public class BackgroundFromForegroundColorConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    
        if (!(value is Color))
            return value;
        Color color = (Color)value;
        double Y = 0.2126 * color.ScR + 0.7152 * color.ScG + 0.0722 * color.ScB;
        return Y > 0.4 ? Brushes.Black : Brushes.White;
    

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    
        throw new NotSupportedException();
    

【问题讨论】:

此处涵盖的类似情况:Make foregroundcolor black or white depending on background、Good text foreground color for a given background color 和 What are your favorite extension methods for C#? 附带说明,ConvertBack 在一种情况下,转换器应该抛出NotSupportedException,因为不会有实现。 【参考方案1】:

有一些计算颜色亮度的方法,基于这些方法,您可以只取黑色或白色背景,并且可以获得不错的可读性。以luma 为例

Y = 0.2126 R + 0.7152 G + 0.0722 B

如果您使用标准化输入值 (0.0 - 1.0),我认为阈值将是 0.5,但我已经有一段时间没有使用它了...

编辑:示例转换实现草图:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

    var c = (Color)value;
    var l = 0.2126 * c.ScR + 0.7152 * c.ScG + 0.0722 * c.ScB;

    return l < 0.5 ? Brushes.White : Brushes.Black;

阈值实际上可能有点取决于显示器和个人偏好,我会更喜欢较低的东西,从而导致黑色背景的份额更大。

【讨论】:

选择黑色或白色似乎可行;现在使用您发布的亮度公式,Y 将在 0 到 255 之间变化;知道我会在哪里画出沙子的线吗? 我想我明白你的意思 0.5: 0.5*255=127.5;如果 > 则使用黑色背景,否则使用白色。带有一系列随机颜色的 AFAICT,看起来效果很好! 这是一种查看方式(您也可以将所有通道除以 255.0 或结果);它确实有效,这就是我之前(两年前)使用它的原因。 您可能还想测试几个阈值,看看哪个是最好的,我会使用一个较低的阈值(例如 0.25),因为计算机显示器上的颜色往往相当明亮。【参考方案2】:

我认为这不仅仅是一个设计问题,而不是一个“正式”的方式。所以这有点取决于你自己的决定。你能展示一些接近你想要达到的目标的例子吗?这些天我也在处理与您的问题类似的事情(创建在线画廊,根据画廊中照片中的颜色动态更改其 BG),我认为我做得很好,我的建议是,无论你选择作为背景,只需在背景中创建一层黑色或白色,具体取决于您的前景色(相反的亮度),这样您在某种意义上“限制”了 BG,例如BG 可以设置为黑色,您的文本也是黑色的,但是 BG 顶部有一个白色层,使文本可读。图层的不透明度留给您,尝试看看什么是最佳值。而且你可以在值转换器中实现整个事情,而 BG + 'layer' 的组合只不过是一个颜色值。

【讨论】:

【参考方案3】:

任何给定颜色 c 的最对比(不同)颜色,您可以轻松获得

new Color(c.R > .5 ? 0 : 1, c.G > .5 ? 0 : 1, c.B > .5 ? 0 : 1)

或者如果您需要 0-255 范围

new Color(c.R > 127 ? 0 : 255, c.G > 127 ? 0 : 255, c.B > 127 ? 0 : 255)

在给定背景上的文本可见性总是最好的,但并不总是很好。如果您不想被疯狂的颜色打扰,您最终只能使用已接受答案建议的黑色/白色。

【讨论】:

【参考方案4】:

在我从事的一个项目中,我们决定使用一个公式,用红绿蓝值分隔颜色,并从 255 中减去红绿和蓝,以获得近乎完美的对比色。

但是...灰色是不适用于此公式的颜色之一。在进行减法之前,您可以简单地检查颜色是否为灰色。在色谱的两端还有一些其他颜色,您可能需要握住他们的手才能获得可读的对比色。

【讨论】:

我不认为这在视觉上会很吸引人,比如青色上的红色,或者洋红色上的绿色看起来不太好看,IMO。但是除非颜色接近灰色,否则无论如何都可以很好地创建对比度。 @can poyrazoğlu - 作者要求找到一种很好的方法来找到光谱另一端颜色的对比度。使用这种方法的红色对比色实际上非常好。黄绿色;我忘了它到底是什么颜色。

以上是关于如何根据字体颜色选择背景颜色以获得适当的对比度的主要内容,如果未能解决你的问题,请参考以下文章

根据背景颜色确定字体颜色

更改一个堆叠条的字体颜色

字体的底色怎么去掉

如何配置Linux命令行的字体和背景颜色

手机字体颜色怎么更改?

eclipse 快速修正的背景颜色以及字体颜色在哪设置