Как выбрать цвет фона в зависимости от цвета шрифта, чтобы иметь правильный контраст
Я не знаю много о цветовой композиции, поэтому я придумал этот алгоритм, который будет выбирать цвет фона на основе цвета шрифта на пробной основе ошибок:
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();
}
}
Я сделал некоторые googling об этом, но я не нашел ничего очень формального о различных способах цвет фона может быть рассчитан, чтобы получить хороший эффект контраста с цветом шрифта.
Итак, мой вопрос: есть ли более "формальный" подход, чтобы выбрать хороший фон, чтобы получить хороший контраст? Кроме того, как бы вы справились с выбором цвета фона с единственной целью сделать ваш текст максимально читаемым независимо от цвета шрифта?
быстрое обновление
немного больше контекста: я просто пытаюсь показать какой-то текст (например "быстрая коричневая лиса прыгает через ленивую собаку"), где пользователь выбирает цвет шрифта, вес шрифта, и т. д. Однако мне интересно посмотреть, что можно сделать, будь то супер просто или больше сложный.
окончательное редактирование
я решил пойти с чем H.B.
suggested: похоже, он отлично работает со всеми цветами, которые я пробовал, в отличие от моего предыдущего алгоритма, передний план не всегда будет контрастировать с фоном. Мне было бы интересно узнать, есть ли формула, которая дает вам "оптимальный" фон для данного переднего плана, но для того, что мне нужно, черный/белый работает просто отлично. Это мой код в его текущей форме:
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 ответов
существуют некоторые методы вычисления яркости цвета, основанные на том, что вы можете просто взять черный или белый фон, и вы получите приличную читаемость. См.Лума
Y = 0,2126 R + 0,7152 G + 0,0722 B
Я думаю, что порог будет 0.5, если вы используете нормализованные входные значения (0.0 - 1.0), но прошло некоторое время с тех пор, как я использовал это...
Edit: пример преобразования эскиз реализации:
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;
}
порог может на самом деле немного зависеть от дисплея и личных предпочтений, я бы предпочел что-то более низкое, что приведет к большей доле черных фонов.
Я думаю, что это больше вопрос дизайна, чем "официальный" способ. Так что это немного к вашему собственному решению. Можете ли вы привести несколько примеров, близких к тому, чего вы пытаетесь достичь? Я также работаю над чем-то похожим на вашу проблему в эти дни (создание онлайн-галереи, которая динамически меняет свой BG в соответствии с цветами на фотографиях в галерее), и я думаю, что я иду довольно хорошо, мой совет заключается в том, что, что бы вы ни выбрали в качестве фона, просто создайте слой черного или белого в фон, в зависимости от вашего цвета переднего плана (противоположная яркость), и таким образом вы в некотором смысле "ограничиваете" BG, например, BG может быть установлен на черный, и ваш текст тоже черный, но поверх BG есть белый слой, который делает текст читаемым. Непрозрачность слоя оставлена вам, попробуйте и посмотрите, что является лучшим значением. И вы можете реализовать все это в преобразователе значений, и эта композиция BG + 'layer' является не более чем значением цвета.
soulution 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)
видимость текста на заданном фоне всегда лучше, но не всегда приятно. В случае, если вы не хотите беспокоить сумасшедшими цветами, вы просто используете черно-белый, предложенный принятым ответом.
в проекте, над которым я работаю, мы решили формулу, которая разделяет цвет на красный зеленый синий и вычитает красный зеленый и синий из 255, чтобы получить почти идеальный цвет.