Подтвердить что ты не робот

Как выбрать цвет фона в зависимости от цвета шрифта, чтобы иметь соответствующий контраст

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

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

Ответ 1

Есть несколько способов вычисления яркости цвета, исходя из того, что вы можете просто взять черный или белый фон, и вы получите достойную читаемость. См. 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;
}

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

Ответ 2

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

Ответ 3

Умение Рамхаунда полностью терпит неудачу для цветов, имеющих каждый компонент около значения 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)

Эта видимость текста на данном фоне всегда лучше, но не всегда приятна. В случае, если вы не хотите нарушать сумасшедшие цвета, вы просто заканчиваете тем, что использовали черный/белый, предлагаемый принятым ответом.

Ответ 4

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

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