Как правильно выбрать цвет фона в зависимости от цвета шрифта - PullRequest
17 голосов
/ 20 июля 2011

Я не знаю много о цветовой композиции, поэтому я придумал этот алгоритм, который будет выбирать цвет фона на основе цвета шрифта на пробной основе на основе ошибок:

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 ]

18 голосов
/ 20 июля 2011

Существуют некоторые методы вычисления яркости цвета, основанные на том, что вы можете просто взять черный или белый фон и получить приличную читаемость. См. luma , например

Y = 0,2126 R + 0,7152 G + 0,0722 B

Я думаю, что порог будет 0,5, если вы используете нормализованные входные значения (0,0 - 1,0), но прошло уже много времени с тех пор, как я использовал это ...

Редактировать: Пример эскиза реализации преобразования:

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

Порог может на самом деле немного зависеть от дисплея и личных предпочтений, я бы предпочел что-то более низкое, что приведет к большей доле черного фона.

3 голосов
/ 01 сентября 2016

Приостановление 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 голосов
/ 20 июля 2011

Я думаю, что это больше, чем проблема дизайна, а не «формальный» способ. Так что это немного по вашему собственному решению. Можете ли вы привести примеры, близкие к тому, чего вы добиваетесь? Я также работаю над чем-то похожим на вашу проблему в эти дни (создаю онлайн-галерею, которая динамически меняет свой BG в соответствии с цветами на фотографиях в галерее), и я думаю, что у меня все идет хорошо, мой совет, что бы вы ни делали выберите в качестве фона, просто создайте слой черного или белого на заднем плане, в зависимости от вашего цвета переднего плана (противоположность его яркости), и таким образом вы в некотором смысле «ограничиваете» BG, например BG может быть установлен на черный, и ваш текст тоже черный, но поверх BG есть белый слой, который делает текст читабельным. Непрозрачность слоя оставлена ​​вам, попробуйте и посмотрите, что является лучшим значением. И вы можете реализовать все это в преобразователе значений, и эта композиция BG + 'layer' является не чем иным, как значением цвета.

1 голос
/ 20 июля 2011

В проекте, над которым я работаю, мы определили формулу, которая разделяет цвет по значениям Red Green Blue и вычитает Red Green и Blue из 255, чтобы получить почти идеальный ограничивающий цвет.

Однако ... Серый - один из тех цветов, которые не будут работать с этой формулой. Вы можете просто проверить, является ли цвет Серым, прежде чем делать вычитание. Есть несколько других цветов на обоих концах цветового спектра, где вам, возможно, придется держать их за руку, чтобы получить читаемый ограничивающий цвет.

...