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

时间:2011-07-20 13:49:43

标签: c# wpf fonts colors contrast

我对颜色构图知之甚少,所以我想出了这个算法,它将根据试错的字体颜色选择背景颜色:

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

4 个答案:

答案 0 :(得分:18)

有一些计算颜色亮度的方法,基于你可以采用黑色或白色背景,你会得到一个不错的可读性。例如,请参阅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;
}

阈值实际上可能有点依赖于显示器和个人偏好,我更喜欢低一些,导致更大的黑色背景份额。

答案 1 :(得分:3)

我认为这不仅仅是一个设计问题,而是一种“正式”方式。所以这是你自己的决定。你能否展示一些与你要实现的目标相近的例子?我现在也在研究类似于你的问题的东西(创建在线画廊,根据画廊中的照片中的颜色动态地改变它的BG),我觉得我很顺利,我的建议是,无论你怎么样选择作为背景,只需在背景中创建一层黑色或白色,具体取决于您的前景色(相反的亮度),这样您就可以“限制”BG,例如BG可以设置为黑色,你的文字也是黑色的,但BG顶部有一个白色层,使文字可读。图层的不透明度留给您,尝试查看最佳值。你可以在价值转换器中实现整个过程,BG +'layer'组合只不过是一个颜色值。

答案 2 :(得分:3)

Ramhound的洗液完全失败,因为每种成分都接近128的颜色(并不是所有的灰色) - 然后你得到几乎相同的颜色!

任何给定颜色的最具对比度(不同)颜色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)

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

答案 3 :(得分:1)

在我研究的项目中,我们决定使用红绿蓝值分离颜色并从255减去红绿和蓝色以获得近乎完美的对比色。

然而......灰色是这种配方无法使用的颜色之一。在进行减法之前,您可以简单地检查颜色是否为灰色。在颜色的两端还有一些其他颜色,你可能需要握住它们以获得可读的颜色。