web-dev-qa-db-ja.com

背景色に基づいてフォントの色を決定する

ユーザーが特定のセクションの背景色をカスタマイズでき、フォントの色はカスタマイズできないシステム(たとえば、オプションの数を最小限に抑えるため)を考えると、「明るい」か「暗い」フォントの色が必要ですか?

何らかのアルゴリズムがあるとは思いますが、色や明度などについて自分で理解するのに十分な知識はありません。

221
Joseph Daigle

同様の問題が発生しました。カラースケール/ヒートマップにテキストラベルを表示するには、対照的なフォントの色を選択する良い方法を見つける必要がありました。それは普遍的な方法でなければならず、生成された色は「見栄えがよく」なければなりませんでした。つまり、単純な補色の生成は良い解決策ではありませんでした。

長時間のテストとこの問題の解決を試みた後、最良の解決策は「暗い」色には白いフォントを選択し、「明るい」色には黒いフォントを選択することであることがわかりました。

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を「知覚輝度」に変更しました-本当に見栄えが良くなりました!すでに私のソフトウェアにそれを実装しており、見栄えが良いです。

Edit 2@WebSeedは、このアルゴリズムの優れた実用例を提供しました: http://codepen.io/WebSeed/full/pvgqEq/

420
Gacek

誰かが 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 値の反転を削除しました(明るい色をより高い値にするには、また、「デフォルト」の計算方法でもあります。

here のGaceKと同じ定数を使用しました。

(次の署名を使用して、これを 拡張メソッド として実装することもできます。

public static Color ContrastColor(this Color iColor)

その後、foregroundColor = background.ContrastColor()経由で呼び出すことができます。)

16

ありがとう@ 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;
}
11
Thomas Vos

Gacekの答えの私のSwift実装:

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)
}
9
vito.royeca

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

これはとても役立つ答えです。それをありがとう!

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
ricotheque

この投稿をありがとう。

興味のある方は、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;
5
Richard D.

私は同じ問題を抱えていましたが、PHPで開発する必要がありました。 @Garekの solution を使用し、この回答も使用しました: PHPで16進数の色をRGB値に変換 HEXカラーコードをRGBに変換.

だから私はそれを共有しています。

この関数は、指定されたBackground 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
GregV

GlyいPython書きたくない場合:)

'''
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'
2
Joseph Coco

Objective-Cの実装

+ (UIColor*) getContrastColor:(UIColor*) color {
    CGFloat red, green, blue, alpha;
    [color getRed:&red green:&green blue:&blue alpha:&alpha];
    double a = ( 0.299 * red + 0.587 * green + 0.114 * blue);
    return (a > 0.5) ? [[UIColor alloc]initWithRed:0 green:0 blue:0 alpha:1] : [[UIColor alloc]initWithRed:255 green:255 blue:255 alpha:1];
}
1
Andreas Lytter

フラッター実装

Color contrastColor(Color color) {
  if (color == Colors.transparent || color.alpha < 50) {
    return Colors.black;
  }
  double luminance = (0.299 * color.red + 0.587 * color.green + 0.114 * color.blue) / 255;
  return luminance > 0.5 ? Colors.black : Colors.white;
}
1
Mamnarock

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

}

UPDATE-0.6がクエリのテストベッドとして優れていることがわかりました

1
RichAppz

iOS Swift 3.0(UIColor拡張):

func isLight() -> Bool
{
    if let components = self.cgColor.components, let firstComponentValue = components[0], let secondComponentValue = components[1], let thirdComponentValue = components[2] {
        let firstComponent = (firstComponentValue * 299)
        let secondComponent = (secondComponentValue * 587)
        let thirdComponent = (thirdComponentValue * 114)
        let brightness = (firstComponent + secondComponent + thirdComponent) / 1000

        if brightness < 0.5
        {
            return false
        }else{
            return true
        }
    }  

    print("Unable to grab components and determine brightness")
    return nil
}
1
Josh O'Connor

色相の背景に色相のテキストを配置して、読みやすくすることができます。私はいつもそれをします。 カラーの読み取り可能なテキスト– STW * のJavascriptには、これに関する式があります。そのリンクで述べているように、式は逆ガンマ調整計算のバリエーションです。そのリンクとその関連ページの右側にあるメニューでは、テキストと背景にランダムに生成された色が使用され、常に読みやすくなっています。それで、はい、明らかにそれを行うことができます、問題ありません。

0
Dave Collier

Kotlin/Android拡張として:

fun Int.getContrastColor(): Int {
    // Counting the perceptive luminance - human eye favors green color...
    val a = 1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255
    return if (a < 0.5) Color.BLACK else Color.WHITE
}
0
Gabriel

視覚効果のために色空間を操作している場合、一般的にRGBよりもHSL(色相、彩度、明度)で作業する方が簡単です。 RGBで色を移動して自然に心地よい効果を与えることは、概念上非常に難しい傾向がありますが、HSLに変換し、そこで操作し、再び変換することは、概念がより直感的で、常に見栄えの良い結果をもたらします。

ウィキペディアには、HSLと密接に関連するHSVへの 良い紹介 があります。そして、変換を行うためのネットの周りに無料のコードがあります(たとえば ここにjavascriptの実装があります

どのような正確な変換を使用するかは好みの問題ですが、個人的には色相と明度のコンポーネントを逆にすると、最初の近似として良好なハイコントラストカラーが生成されると確信していましたが、より微妙な効果を簡単に得ることができます。

0
Cruachan

アルファもキャプチャするAndroidバリエーション

(ありがとう@ thomas-vos)

/**
 * Returns a colour best suited to contrast with the input colour.
 *
 * @param colour
 * @return
 */
@ColorInt
public static int contrastingColour(@ColorInt int colour) {
    // XXX https://stackoverflow.com/questions/1855884/determine-font-color-based-on-background-color

    // Counting the perceptive luminance - human eye favors green color...
    double a = 1 - (0.299 * Color.red(colour) + 0.587 * Color.green(colour) + 0.114 * Color.blue(colour)) / 255;
    int alpha = Color.alpha(colour);

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

    return Color.argb(alpha, d, d, d);
}
0
Brill Pappin