回答:
個々の赤、緑、青の強度を取得するには、16進コードを3つに分割する必要があります。コードの各2桁は、16進数(base-16)表記の値を表します。ここでは変換の詳細については触れません。簡単に調べることができます。
個々の色の強度を取得したら、色の全体的な強度を決定し、対応するテキストを選択できます。
if (red*0.299 + green*0.587 + blue*0.114) > 186 use #000000 else use #ffffff
しきい値の186は理論に基づいていますが、好みに合わせて調整できます。しきい値以下のコメントに基づくと、150の方が効果的です。
W3C勧告のコントラストに対して与えられる式は(L1 + 0.05) / (L2 + 0.05)
、です。ここL1
で、L2
は0.0〜1.0のスケールで最も明るい色の輝度と最も暗い色の輝度です。黒の輝度は0.0、白は1.0であるため、これらの値を代入すると、コントラストが最も高い値を決定できます。黒のコントラストが白のコントラストより大きい場合は黒を使用し、それ以外の場合は白を使用します。L
テストが次のようになると、テストしている色の輝度が与えられます。
if (L + 0.05) / (0.0 + 0.05) > (1.0 + 0.05) / (L + 0.05) use #000000 else use #ffffff
これにより代数的に簡略化され、次のようになります。
if L > sqrt(1.05 * 0.05) - 0.05
またはおよそ:
if L > 0.179 use #000000 else use #ffffff
残っているのは計算することだけですL
。この式はガイドラインにも記載されており、sRGBからリニアRGBへの変換の後に、輝度に関するITU-R勧告BT.709が続くように見えます。
for each c in r,g,b:
c = c / 255.0
if c <= 0.03928 then c = c/12.92 else c = ((c+0.055)/1.055) ^ 2.4
L = 0.2126 * r + 0.7152 * g + 0.0722 * b
しきい値0.179はW3Cガイドラインに関連付けられているため、変更しないでください。結果が気に入らない場合は、上記の簡単な式を試してください。
#D6B508
の値は171になり、コントラストが白になります。ただし、コントラストは黒である必要があります(ここで確認:webaim.org/resources/contrastchecker)
私のコードではないため、このコードは信用しませんが、他の人が将来すぐに見つけられるように、ここに残します。
Mark Ransomsの回答に基づいて、シンプルなバージョンのコードスニペットを次に示します。
function pickTextColorBasedOnBgColorSimple(bgColor, lightColor, darkColor) {
var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
var r = parseInt(color.substring(0, 2), 16); // hexToR
var g = parseInt(color.substring(2, 4), 16); // hexToG
var b = parseInt(color.substring(4, 6), 16); // hexToB
return (((r * 0.299) + (g * 0.587) + (b * 0.114)) > 186) ?
darkColor : lightColor;
}
高度なバージョンのコードスニペットは次のとおりです。
function pickTextColorBasedOnBgColorAdvanced(bgColor, lightColor, darkColor) {
var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
var r = parseInt(color.substring(0, 2), 16); // hexToR
var g = parseInt(color.substring(2, 4), 16); // hexToG
var b = parseInt(color.substring(4, 6), 16); // hexToB
var uicolors = [r / 255, g / 255, b / 255];
var c = uicolors.map((col) => {
if (col <= 0.03928) {
return col / 12.92;
}
return Math.pow((col + 0.055) / 1.055, 2.4);
});
var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);
return (L > 0.179) ? darkColor : lightColor;
}
それらを使用するには、次を呼び出します。
var color = '#EEACAE' // this can be any color
pickTextColorBasedOnBgColorSimple(color, '#FFFFFF', '#000000');
また、ありがとうAlx
とchetstone
。
isDark(bgColor)
私の使用量はちょうどそのある'color': isDark(color)?'white':'black'
これ(JavaScriptコード)はどうですか?
/**
* Get color (black/white) depending on bgColor so it would be clearly seen.
* @param bgColor
* @returns {string}
*/
getColorByBgColor(bgColor) {
if (!bgColor) { return ''; }
return (parseInt(bgColor.replace('#', ''), 16) > 0xffffff / 2) ? '#000' : '#fff';
}
算術ソリューションに加えて、AIニューラルネットワークを使用することも可能です。利点は、自分の好みやニーズに合わせて調整できることです(明るい飽和赤のオフホワイトのテキストは見栄えがよく、黒と同じくらい読みやすくなっています)。
これは、概念を説明するきちんとしたJavascriptデモです。デモで直接、独自のJS式を生成することもできます。
https://harthur.github.io/brain/
以下は、問題を理解するのに役立ついくつかのグラフです。最初のグラフでは、明度は一定の128ですが、色相と彩度は異なります。2番目のグラフでは、彩度は定数255ですが、色相と明度は異なります。
AndroidのJavaでの私の解決策は次のとおりです。
// Put this method in whichever class you deem appropriate
// static or non-static, up to you.
public static int getContrastColor(int colorIntValue) {
int red = Color.red(colorIntValue);
int green = Color.green(colorIntValue);
int blue = Color.blue(colorIntValue);
double lum = (((0.299 * red) + ((0.587 * green) + (0.114 * blue))));
return lum > 186 ? 0xFF000000 : 0xFFFFFFFF;
}
// Usage
// If Color is represented as HEX code:
String colorHex = "#484588";
int color = Color.parseColor(colorHex);
// Or if color is Integer:
int color = 0xFF484588;
// Get White (0xFFFFFFFF) or Black (0xFF000000)
int contrastColor = WhateverClass.getContrastColor(color);
@MarkRansomの回答に基づいて、次の場所にあるPHPスクリプトを作成しました。
function calcC($c) {
if ($c <= 0.03928) {
return $c / 12.92;
}
else {
return pow(($c + 0.055) / 1.055, 2.4);
}
}
function cutHex($h) {
return ($h[0] == "#") ? substr($h, 1, 7) : $h;
}
function hexToR($h) {
return hexdec(substr(cutHex($h), 0, 2));
}
function hexToG($h) {
return hexdec(substr(cutHex($h), 2, 2)); // Edited
}
function hexToB($h) {
return hexdec(substr(cutHex($h), 4, 2)); // Edited
}
function computeTextColor($color) {
$r = hexToR($color);
$g = hexToG($color);
$b = hexToB($color);
$uicolors = [$r / 255, $g / 255, $b / 255];
$c = array_map("calcC", $uicolors);
$l = 0.2126 * $c[0] + 0.7152 * $c[1] + 0.0722 * $c[2];
return ($l > 0.179) ? '#000000' : '#ffffff';
}
これは、UIColorの拡張としてのMark Ransomの回答の迅速なバージョンです。
extension UIColor {
// Get the rgba components in CGFloat
var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
/// Return the better contrasting color, white or black
func contrastColor() -> UIColor {
let rgbArray = [rgba.red, rgba.green, rgba.blue]
let luminanceArray = rgbArray.map({ value -> (CGFloat) in
if value < 0.03928 {
return (value / 12.92)
} else {
return (pow( (value + 0.55) / 1.055, 2.4) )
}
})
let luminance = 0.2126 * luminanceArray[0] +
0.7152 * luminanceArray[1] +
0.0722 * luminanceArray[2]
return luminance > 0.179 ? UIColor.black : UIColor.white
} }
これは、要素をクリックしたときにSVGチェックマークの色を変更する例にすぎません。クリックされた要素の背景色に基づいて、チェックマークの色を黒または白に設定します。
checkmarkColor: function(el) {
var self = el;
var contrast = function checkContrast(rgb) {
// @TODO check for HEX value
// Get RGB value between parenthesis, and remove any whitespace
rgb = rgb.split(/\(([^)]+)\)/)[1].replace(/ /g, '');
// map RGB values to variables
var r = parseInt(rgb.split(',')[0], 10),
g = parseInt(rgb.split(',')[1], 10),
b = parseInt(rgb.split(',')[2], 10),
a;
// if RGBA, map alpha to variable (not currently in use)
if (rgb.split(',')[3] !== null) {
a = parseInt(rgb.split(',')[3], 10);
}
// calculate contrast of color (standard grayscale algorithmic formula)
var contrast = (Math.round(r * 299) + Math.round(g * 587) + Math.round(b * 114)) / 1000;
return (contrast >= 128) ? 'black' : 'white';
};
$('#steps .step.color .color-item .icon-ui-checkmark-shadow svg').css({
'fill': contrast($(self).css('background-color'))
});
}
onClickExtColor: function(evt) {
var self = this;
self.checkmarkColor(evt.currentTarget);
}
このJavaScript関数を使用して、rgb
/ またはに変換rgba
します。'white'
'black'
function getTextColor(rgba) {
rgba = rgba.match(/\d+/g);
if ((rgba[0] * 0.299) + (rgba[1] * 0.587) + (rgba[2] * 0.114) > 186) {
return 'black';
} else {
return 'white';
}
}
これらの形式のいずれかを入力すると、出力'black'
または'white'
rgb(255,255,255)
rgba(255,255,255,0.1)
color:rgba(255,255,255,0.1)
255,255,255,0.1
マークの詳細な答えは素晴らしいです。JavaScriptでの実装は次のとおりです。
function lum(rgb) {
var lrgb = [];
rgb.forEach(function(c) {
c = c / 255.0;
if (c <= 0.03928) {
c = c / 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
lrgb.push(c);
});
var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
return (lum > 0.179) ? '#000000' : '#ffffff';
}
次に、この関数lum([111, 22, 255])
を呼び出して白または黒を取得できます。
リンクからのさまざまな入力に基づいて、背景に応じて前景色を黒または白にします。とこのスレッドに、必要なコントラスト色を提供するColorの拡張クラスを作成しました。
コードは以下のようになります:
public static class ColorExtension
{
public static int PerceivedBrightness(this Color c)
{
return (int)Math.Sqrt(
c.R * c.R * .299 +
c.G * c.G * .587 +
c.B * c.B * .114);
}
public static Color ContrastColor(this Color iColor, Color darkColor,Color lightColor)
{
// Counting the perceptive luminance (aka luma) - human eye favors green color...
double luma = (iColor.PerceivedBrightness() / 255);
// Return black for bright colors, white for dark colors
return luma > 0.5 ? darkColor : lightColor;
}
public static Color ContrastColor(this Color iColor) => iColor.ContrastColor(Color.Black);
public static Color ContrastColor(this Color iColor, Color darkColor) => iColor.ContrastColor(darkColor, Color.White);
// Converts a given Color to gray
public static Color ToGray(this Color input)
{
int g = (int)(input.R * .299) + (int)(input.G * .587) + (int)(input.B * .114);
return Color.FromArgb(input.A, g, g, g);
}
}
これは、ベースRのみを使用したMark Ransomの回答のRバージョンです。
hex_bw <- function(hex_code) {
myrgb <- as.integer(col2rgb(hex_code))
rgb_conv <- lapply(myrgb, function(x) {
i <- x / 255
if (i <= 0.03928) {
i <- i / 12.92
} else {
i <- ((i + 0.055) / 1.055) ^ 2.4
}
return(i)
})
rgb_calc <- (0.2126*rgb_conv[[1]]) + (0.7152*rgb_conv[[2]]) + (0.0722*rgb_conv[[3]])
if (rgb_calc > 0.179) return("#000000") else return("#ffffff")
}
> hex_bw("#8FBC8F")
[1] "#000000"
> hex_bw("#7fa5e3")
[1] "#000000"
> hex_bw("#0054de")
[1] "#ffffff"
> hex_bw("#2064d4")
[1] "#ffffff"
> hex_bw("#5387db")
[1] "#000000"
@SoBiT、私はあなたの答えを見ていました、それはよさそうですが、それには小さな間違いがあります。関数hexToGとhextoBは、少し編集する必要があります。substrの最後の数値は文字列の長さなので、この場合は4または6ではなく「2」になります。
function hexToR($h) {
return hexdec(substr(cutHex($h), 0, 2));
}
function hexToG($h) {
return hexdec(substr(cutHex($h), 2, 2));
}
function hexToB($h) {
return hexdec(substr(cutHex($h), 4, 2));
}
LESSには、contrast()
私にとってうまく機能する素晴らしい機能があります。http://lesscss.org/functions/#color-operations-contrastを参照してください
「2つの色のどちらを選択すると、他の色とのコントラストが最も大きくなります。これは、背景に対して色を読みやすくするのに役立ちます。これは、アクセシビリティ準拠にも役立ちます。この関数は、SAS for Compassのコントラスト関数と同じように機能します。 WCAG 2.0に従って、色は明度ではなく、ガンマ補正された輝度値を使用して比較されます。」
例:
p {
a: contrast(#bbbbbb);
b: contrast(#222222, #101010);
c: contrast(#222222, #101010, #dddddd);
d: contrast(hsl(90, 100%, 50%), #000000, #ffffff, 30%);
e: contrast(hsl(90, 100%, 50%), #000000, #ffffff, 80%);
}
出力:
p {
a: #000000 // black
b: #ffffff // white
c: #dddddd
d: #000000 // black
e: #ffffff // white
}
六角から黒または白へ:
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
]
: [0, 0, 0];
}
function lum(hex) {
var rgb = hexToRgb(hex)
var lrgb = [];
rgb.forEach(function(c) {
c = c / 255.0;
if (c <= 0.03928) {
c = c / 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
lrgb.push(c);
});
var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
return lum > 0.179 ? "#000000" : "#ffffff";
}
Markの回答に基づくiOSのObjective-cバージョンコード:
- (UIColor *)contrastForegroundColor {
CGFloat red = 0, green = 0, blue = 0, alpha = 0;
[self getRed:&red green:&green blue:&blue alpha:&alpha];
NSArray<NSNumber *> *rgbArray = @[@(red), @(green), @(blue)];
NSMutableArray<NSNumber *> *parsedRGBArray = [NSMutableArray arrayWithCapacity:rgbArray.count];
for (NSNumber *item in rgbArray) {
if (item.doubleValue <= 0.03928) {
[parsedRGBArray addObject:@(item.doubleValue / 12.92)];
} else {
double newValue = pow((item.doubleValue + 0.055) / 1.055, 2.4);
[parsedRGBArray addObject:@(newValue)];
}
}
double luminance = 0.2126 * parsedRGBArray[0].doubleValue + 0.7152 * parsedRGBArray[1].doubleValue + 0.0722 * parsedRGBArray[2].doubleValue;
return luminance > 0.179 ? UIColor.blackColor : UIColor.whiteColor;
}
これは私が使用していて、これまで問題がなかった私の独自の方法です😄
const hexCode = value.charAt(0) === '#'
? value.substr(1, 6)
: value;
const hexR = parseInt(hexCode.substr(0, 2), 16);
const hexG = parseInt(hexCode.substr(2, 2), 16);
const hexB = parseInt(hexCode.substr(4, 2), 16);
// Gets the average value of the colors
const contrastRatio = (hexR + hexG + hexB) / (255 * 3);
contrastRatio >= 0.5
? 'black'
: 'white';
背景色のRGBまたはHEX値に基づいて前景色を選択するPythonモジュールを作成しました:https : //github.com/azaitsev/foreground
Markの驚くべき答えに基づくJava Swingのコードは次のとおりです。
public static Color getColorBasedOnBackground(Color background, Color darkColor, Color lightColor) {
// Calculate foreground color based on background (based on https://stackoverflow.com/a/3943023/)
Color color;
double[] cL = new double[3];
double[] colorRGB = new double[] {background.getRed(), background.getGreen(), background.getBlue()};
for (int i = 0; i < colorRGB.length; i++)
cL[i] = (colorRGB[i] / 255.0 <= 0.03928) ? colorRGB[i] / 255.0 / 12.92 :
Math.pow(((colorRGB[i] / 255.0 + 0.055) / 1.055), 2.4);
double L = 0.2126 * cL[0] + 0.7152 * cL[1] + 0.0722 * cL[2];
color = (L > Math.sqrt(1.05 * 0.05) - 0.05) ? darkColor : lightColor;
return color;
}