Программно выбирайте высококонтрастные цвета
Это должен быть простой вопрос, но я не смог найти способ заставить его работать.
По сути, у меня есть глупая страница localhost, которую я использую в своем веб-дизайне. Когда я занимаюсь серфингом между нашим сервером разработки и моей локальной версией кода С# (перенаправляется с dev url через файл хоста), я, как известно, иногда забываю, что указывает "dev.foo.com" - локальный или сервер.
Итак, я создал страницу, которая будет запускаться локально как моя страница по умолчанию для веб-страницы по умолчанию, поэтому я могу легко идентифицировать свой локальный хост с сервера.
Эта страница делает много вещей случайным образом (включая создание стартовой статистики для D & D), включая установку случайного цвета фона. Я делаю это, генерируя 3 случайных числа между 0 и 255 и устанавливая их как значение RGB для цвета фона тела в CSS.
Учитывая 3 ints R, G и B, как определить R2, G2 и B2, чтобы второй цвет имел высокий контраст с первым? Мне нравится, когда страница имеет случайные цвета фона (это мешает мне привыкнуть к виду целевой страницы), но мне также нравится читать текст.
Ответы
Ответ 1
Вам нужно различие в яркости для текста, чтобы быть читаемым, так как цветное зрение имеет слишком низкое разрешение.
Итак, в качестве алгоритма я предлагаю следующее:
-
Выберите случайный цвет фона.
-
Затем определите, светлый или темный цвет. Например, вы можете проверить, больше ли среднее из трех основных цветов или равно 128.
-
Для светлого цвета используйте черный текст, для темного одного белого текста.
Ответ 2
"Контрастность" - это загруженное слово. Если вам просто нужно читать текст, тогда один простой способ - работать в цветовом пространстве на основе яркости, таком как HSL, и выбирать цвета переднего плана и фона с большими различиями в яркости.
Преобразование между HSL и RGB хорошо известно - подробности см. в Википедии.
Если вы говорите о фактическом цветовом контрасте, это не так, как вырезано-высушено (есть много перцептивных факторов, которые, насколько я знаю, не были сведены к одному цветовому пространству) но я подозреваю, что вам не нужен этот уровень сложности.
Ответ 3
Посмотрите это решение PHP: Вычисление цветового контраста с PHP Андреасом Гором. Его можно портировать на любой язык, конечно.
У него также очень хорошая демонстрация его анализатора контраста, где вы можете найти минимальные уровни контрастности для работы.
Ответ 4
Вы можете использовать метод GetBrightness()
в классе Color
. Он возвращает значение float от 0.0 (яркость черного) до 1.0 (белый).
Простое решение:
var color1 = new Color.FromArgb(r1, g1, b1);
var brightness = color1.GetBrightness();
var color2 = brightness > 0.5 ? Color.Black : Color.White;
Ответ 5
Я сделал что-то подобное в приложении Palm OS. Это то, что я придумал. Он не дает вам "высококонтрастные" цвета, но дает вам цвет фона, который достаточно отличается от цвета текста, чтобы быть вполне читаемым:
// Black background is a special case. It fairly likely to occur and
// the default color shift we do isn't very noticeable with very dark colors.
if (backColor.r < 0x20 && backColor.g < 0x20 && backColor.b < 0x20)
{
textColor.r = backColor.r + 0x20;
textColor.g = backColor.g + 0x20;
textColor.b = backColor.b + 0x20;
}
else
{
textColor.r = backColor.r + ((backColor.r < 128) ? 0x10 : -0x10);
textColor.g = backColor.g + ((backColor.g < 128) ? 0x10 : -0x10);
textColor.b = backColor.b + ((backColor.b < 128) ? 0x10 : -0x10);
}
Возможно, вам не нужно делать черные в качестве специального случая для ваших целей - обработка цвета на ладони немного фанки (16-битный цвет).
Ответ 6
Есть несколько хороших ресурсов (и алгоритмов) для решения этой проблемы на http://juicystudio.com/article/luminositycontrastratioalgorithm.php
Ответ 7
Если вы перевернете все биты, вы получите "противоположный" цвет, который будет довольно хорошим контрастом.
Я считаю, что оператор ~ в С#:
R2 = ~R1;
G2 = ~G1;
B2 = ~B1;
Ответ 8
Для лучшего контраста используйте этот код
function lumdiff($R1,$G1,$B1,$R2,$G2,$B2){
$L1 = 0.2126 * pow($R1/255, 2.2) +
0.7152 * pow($G1/255, 2.2) +
0.0722 * pow($B1/255, 2.2);
$L2 = 0.2126 * pow($R2/255, 2.2) +
0.7152 * pow($G2/255, 2.2) +
0.0722 * pow($B2/255, 2.2);
if($L1 > $L2){
return ($L1+0.05) / ($L2+0.05);
}else{
return ($L2+0.05) / ($L1+0.05);
}
}
function get_the_contrast($c1, $c2) {
return (lumdiff(hexdec(substr($c1,0,2)),
hexdec(substr($c1,2,2)),hexdec(substr($c1,4,2)),
hexdec(substr($c2,0,2)),hexdec(substr($c2,2,2)),
hexdec(substr($c2,4,2))));
}
Метод выше (AVG (красный, зеленый, синий) > 128) не очень хорош.
Ответ 9
private Color GetContrastingColor(Color color)
{
int r = color.R > 0 ? 256 - color.R : 255;
int g = color.G > 0 ? 256 - color.G : 255;
int b = color.B > 0 ? 256 - color.B : 255;
return System.Drawing.Color.FromArgb(r, g, b);
}
Ответ 10
Благодаря @starblue!
Вот код C#
, который я использую
public static string GetContrastBlackOrWhiteColorAsHtmlColorCode(Color c)
{
System.Drawing.Color color = System.Drawing.ColorTranslator.FromHtml("transparent");
try
{
if (c.R >= 128 && c.G >= 128 && c.B >= 128)
{
return System.Drawing.ColorTranslator.ToHtml(Color.Black);
}
else
{
return System.Drawing.ColorTranslator.ToHtml(Color.White);
}
}
catch (Exception)
{
}
return System.Drawing.ColorTranslator.ToHtml(color);
}
Ответ 11
Эти ответы более или менее предлагают использовать один из двух или трех вариантов цвета в зависимости от того, является ли цвет ярким или темным.
Я использую немного другой подход, и он работал элегантно в моем случае. Вот реализация.
int color = your_color;
contrastColor = Color.rgb(255-(color >> 16)&0xFF, 255-(color >> 8)&0xFF, 255- color&0xFF);
Это просто и замечательно.