Определите цвет шрифта на основе цвета фона - PullRequest
217 голосов
/ 06 декабря 2009

Учитывая систему (например, веб-сайт), которая позволяет пользователю настраивать цвет фона для некоторого раздела, но не цвет шрифта (чтобы свести к минимуму количество параметров), существует ли способ программно определить, светится ли индикатор "или" темный "цвет шрифта необходим?

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

Ответы [ 17 ]

415 голосов
/ 06 декабря 2009

Я столкнулся с подобной проблемой. Мне нужно было найти хороший метод выбора цвета контрастного шрифта для отображения текстовых меток на цветовых шкалах / тепловых картах. Это должен был быть универсальный метод, а генерируемый цвет должен быть «хорошо выглядящим», а это значит, что простое генерирование дополнительного цвета не было хорошим решением - иногда оно генерировало странные, очень интенсивные цвета, которые было трудно смотреть и читать.

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

Вот пример функции, которую я использую в C #:

Color ContrastColor(Color color)
{
    int d = 0;

    // Counting the perceptive luminance - human eye favors green color... 
    double luminance = ( 0.299 * color.R + 0.587 * color.G + 0.114 * color.B)/255;

    if (luminance > 0.5)
       d = 0; // bright colors - black font
    else
       d = 255; // dark colors - white font

    return  Color.FromArgb(d, d, d);
}

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

Редактировать
Изменена формула подсчета a на «воспринимаемую яркость» - она ​​действительно выглядит лучше! Уже реализовал это в моем программном обеспечении, отлично выглядит.

Редактировать 2 @WebSeed предоставил отличный рабочий пример этого алгоритма: http://codepen.io/WebSeed/full/pvgqEq/

13 голосов
/ 27 апреля 2016

На всякий случай, если кто-то захочет получить более короткую, возможно, более понятную версию ответа GaceK :

public Color ContrastColor(Color iColor)
{
   // Calculate the perceptive luminance (aka luma) - human eye favors green color... 
   double luma = ((0.299 * iColor.R) + (0.587 * iColor.G) + (0.114 * iColor.B)) / 255;

   // Return black for bright colors, white for dark colors
   return luma > 0.5 ? Color.Black : Color.White;
}

Примечание: Я убрал инверсию значения luma (чтобы яркие цвета имели более высокое значение, что мне кажется более естественным, а также метод расчета по умолчанию .

Я использовал те же константы, что и GaceK, из здесь , так как они отлично работали для меня.

(Вы также можете реализовать это как метод расширения , используя следующую подпись:

public static Color ContrastColor(this Color iColor)

Вы можете позвонить по номеру foregroundColor = background.ContrastColor().)

11 голосов
/ 26 декабря 2016

Спасибо @ Gacek . Вот версия для Android:

@ColorInt
public static int getContrastColor(@ColorInt int color) {
    // Counting the perceptive luminance - human eye favors green color...
    double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;

    int d;
    if (a < 0.5) {
        d = 0; // bright colors - black font
    } else {
        d = 255; // dark colors - white font
    }

    return Color.rgb(d, d, d);
}

И улучшенная (более короткая) версия:

@ColorInt
public static int getContrastColor(@ColorInt int color) {
    // Counting the perceptive luminance - human eye favors green color...
    double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255;
    return a < 0.5 ? Color.BLACK : Color.WHITE;
}
9 голосов
/ 19 мая 2016

My Swift реализация ответа Gacek:

func contrastColor(color: UIColor) -> UIColor {
    var d = CGFloat(0)

    var r = CGFloat(0)
    var g = CGFloat(0)
    var b = CGFloat(0)
    var a = CGFloat(0)

    color.getRed(&r, green: &g, blue: &b, alpha: &a)

    // Counting the perceptive luminance - human eye favors green color...
    let luminance = 1 - ((0.299 * r) + (0.587 * g) + (0.114 * b))

    if luminance < 0.5 {
        d = CGFloat(0) // bright colors - black font
    } else {
        d = CGFloat(1) // dark colors - white font
    }

    return UIColor( red: d, green: d, blue: d, alpha: a)
}
7 голосов
/ 18 июня 2017

Javascript [ES2015]

const hexToLuma = (colour) => {
    const hex   = colour.replace(/#/, '');
    const r     = parseInt(hex.substr(0, 2), 16);
    const g     = parseInt(hex.substr(2, 2), 16);
    const b     = parseInt(hex.substr(4, 2), 16);

    return [
        0.299 * r,
        0.587 * g,
        0.114 * b
    ].reduce((a, b) => a + b) / 255;
};
5 голосов
/ 04 июля 2016

Это такой полезный ответ. Спасибо за это!

Я хотел бы поделиться версией SCSS:

@function is-color-light( $color ) {

  // Get the components of the specified color
  $red: red( $color );
  $green: green( $color );
  $blue: blue( $color );

  // Compute the perceptive luminance, keeping
  // in mind that the human eye favors green.
  $l: 1 - ( 0.299 * $red + 0.587 * $green + 0.114 * $blue ) / 255;
  @return ( $l < 0.5 );

}

Теперь выясним, как использовать алгоритм для автоматического создания парящих цветов для ссылок меню Светлые заголовки становятся темнее, и наоборот.

5 голосов
/ 17 декабря 2015

Спасибо за этот пост.

Для тех, кто может быть заинтересован, вот пример этой функции в Delphi:

function GetContrastColor(ABGColor: TColor): TColor;
var
  ADouble: Double;
  R, G, B: Byte;
begin
  if ABGColor <= 0 then
  begin
    Result := clWhite;
    Exit; // *** EXIT RIGHT HERE ***
  end;

  if ABGColor = clWhite then
  begin
    Result := clBlack;
    Exit; // *** EXIT RIGHT HERE ***
  end;

  // Get RGB from Color
  R := GetRValue(ABGColor);
  G := GetGValue(ABGColor);
  B := GetBValue(ABGColor);

  // Counting the perceptive luminance - human eye favors green color...
  ADouble := 1 - (0.299 * R + 0.587 * G + 0.114 * B) / 255;

  if (ADouble < 0.5) then
    Result := clBlack  // bright colors - black font
  else
    Result := clWhite;  // dark colors - white font
end;
2 голосов
/ 16 мая 2018

У меня была такая же проблема, но мне пришлось разработать ее на PHP . Я использовал решение @ Garek , и я также использовал этот ответ: Преобразование шестнадцатеричного цвета в значения RGB в PHP для преобразования цветового кода HEX в RGB.

Так что я делюсь этим.

Я хотел использовать эту функцию с заданным фоновым HEX-цветом, но не всегда начиная с '#'.

//So it can be used like this way:
$color = calculateColor('#804040');
echo $color;

//or even this way:
$color = calculateColor('D79C44');
echo '<br/>'.$color;

function calculateColor($bgColor){
    //ensure that the color code will not have # in the beginning
    $bgColor = str_replace('#','',$bgColor);
    //now just add it
    $hex = '#'.$bgColor;
    list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x");
    $color = 1 - ( 0.299 * $r + 0.587 * $g + 0.114 * $b)/255;

    if ($color < 0.5)
        $color = '#000000'; // bright colors - black font
    else
        $color = '#ffffff'; // dark colors - white font

    return $color;
}
2 голосов
/ 03 июня 2016

Гадкий Питон, если тебе не хочется его писать:)

'''
Input a string without hash sign of RGB hex digits to compute
complementary contrasting color such as for fonts
'''
def contrasting_text_color(hex_str):
    (r, g, b) = (hex_str[:2], hex_str[2:4], hex_str[4:])
    return '000' if 1 - (int(r, 16) * 0.299 + int(g, 16) * 0.587 + int(b, 16) * 0.114) / 255 < 0.5 else 'fff'
1 голос
/ 08 июня 2018

Swift 4 Пример:

extension UIColor {

    var isLight: Bool {
        let components = cgColor.components

        let firstComponent = ((components?[0]) ?? 0) * 299
        let secondComponent = ((components?[1]) ?? 0) * 587
        let thirdComponent = ((components?[2]) ?? 0) * 114
        let brightness = (firstComponent + secondComponent + thirdComponent) / 1000

        return !(brightness < 0.6)
    }

}

ОБНОВЛЕНИЕ - Обнаружено, что 0.6 был лучшим испытательным стендом для запроса

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...