Программно выбирать высококонтрастные цвета

StackOverflow https://stackoverflow.com/questions/407793

  •  03-07-2019
  •  | 
  •  

Вопрос

Это должен быть простой вопрос, но я не смог найти способ заставить его работать.

По сути, у меня есть дурацкая страница localhost, которую я использую в своей веб-разработке.Когда я просматриваю между нашим сервером разработки и моей локальной версией кода C# (перенаправленной с URL-адреса разработчика через файл хоста), я, как известно, иногда забываю, на что указывает «dev.foo.com» - локальный или серверный.

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

На этой странице многие вещи выполняются случайным образом (в том числе генерируются стартовые характеристики персонажа для D&D), включая установку случайного цвета фона.Я делаю это, генерируя 3 случайных числа от 0 до 255 и устанавливая их в качестве значения RGB для цвета фона тела в CSS.

Учитывая 3 целых числа R, G и B, как мне определить R2, G2 и B2 так, чтобы второй цвет имел высокий контраст с первым?Мне нравится, когда страница имеет случайные цвета фона (это мешает мне привыкнуть к внешнему виду целевой страницы), но мне также нравится иметь возможность читать текст.

Это было полезно?

Решение

Чтобы текст был читаемым, вам нужна разница в яркости, поскольку цветовое зрение само по себе имеет слишком низкое разрешение.

В качестве алгоритма я бы предложил следующий:

  • Выберите случайный цвет фона.

  • Затем решите, светлый это цвет или темный.Например, вы можете проверить, больше или равно среднее значение трех основных цветов 128.

  • Для светлого цвета используйте черный текст, для темного — белый.

Другие советы

«Контраст» — громкое слово.Если вас просто заботит возможность читать текст, то один из простых способов — работать в цветовом пространстве, основанном на яркости, таком как HSL, и выбирать цвета переднего плана и фона с большой разницей в яркости.

Преобразование между HSL и RGB хорошо известно — подробности см. в Википедии.

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

Посмотрите это PHP-решение: Вычисление цветового контраста с помощью PHP Андреас Гор.Конечно, его можно портировать на любой язык.

У него также есть очень хорошая демонстрация его анализатора контрастности, где вы можете найти минимальные уровни контрастности для работы.

Вы можете использовать метод GetBrightness() на Color сорт.Он возвращает плавающее значение от 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;

Я сделал что-то подобное в приложении Palm OS.Вот что я придумал.Он не дает вам «высококонтрастных» цветов, но дает цвет фона, который достаточно отличается от цвета текста, чтобы его можно было легко читать:

  // Black background is a special case.  It's 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);
  }

Возможно, вам не понадобится использовать черный цвет в качестве особого случая для ваших целей — обработка цвета у Palm немного странная (16-битный цвет).

Есть несколько хороших ресурсов (и алгоритмов) для решения этой проблемы: http://juicystudio.com/article/luminositycontrastratioalgorithm.php

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

Я использую немного другой подход, и в моем случае он сработал элегантно.Вот реализация.

 int color = your_color;
 contrastColor = Color.rgb(255-(color >> 16)&0xFF, 255-(color >> 8)&0xFF, 255- color&0xFF);

Это просто и чудесно.

Если вы перевернете все биты, вы получите «противоположный» цвет, который будет довольно хорошим контрастом.

Я считаю, что это оператор ~ в С#:

R2 = ~R1;
G2 = ~G1;
B2 = ~B1;

Для лучшего контраста используйте этот код

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(red,green,blue) > 128) не очень хорош.

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

Благодаря @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);
        }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top