给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
当前回答
丑陋的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'
其他回答
请注意,在谷歌闭包库中有一个算法,该算法引用了w3c推荐:http://www.w3.org/TR/AERT#color-contrast。但是,在这个API中,您提供了一个建议颜色列表作为起点。
/**
* Find the "best" (highest-contrast) of the suggested colors for the prime
* color. Uses W3C formula for judging readability and visual accessibility:
* http://www.w3.org/TR/AERT#color-contrast
* @param {goog.color.Rgb} prime Color represented as a rgb array.
* @param {Array<goog.color.Rgb>} suggestions Array of colors,
* each representing a rgb array.
* @return {!goog.color.Rgb} Highest-contrast color represented by an array.
*/
goog.color.highContrast = function(prime, suggestions) {
var suggestionsWithDiff = [];
for (var i = 0; i < suggestions.length; i++) {
suggestionsWithDiff.push({
color: suggestions[i],
diff: goog.color.yiqBrightnessDiff_(suggestions[i], prime) +
goog.color.colorDiff_(suggestions[i], prime)
});
}
suggestionsWithDiff.sort(function(a, b) { return b.diff - a.diff; });
return suggestionsWithDiff[0].color;
};
/**
* Calculate brightness of a color according to YIQ formula (brightness is Y).
* More info on YIQ here: http://en.wikipedia.org/wiki/YIQ. Helper method for
* goog.color.highContrast()
* @param {goog.color.Rgb} rgb Color represented by a rgb array.
* @return {number} brightness (Y).
* @private
*/
goog.color.yiqBrightness_ = function(rgb) {
return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
};
/**
* Calculate difference in brightness of two colors. Helper method for
* goog.color.highContrast()
* @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
* @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
* @return {number} Brightness difference.
* @private
*/
goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
return Math.abs(
goog.color.yiqBrightness_(rgb1) - goog.color.yiqBrightness_(rgb2));
};
/**
* Calculate color difference between two colors. Helper method for
* goog.color.highContrast()
* @param {goog.color.Rgb} rgb1 Color represented by a rgb array.
* @param {goog.color.Rgb} rgb2 Color represented by a rgb array.
* @return {number} Color difference.
* @private
*/
goog.color.colorDiff_ = function(rgb1, rgb2) {
return Math.abs(rgb1[0] - rgb2[0]) + Math.abs(rgb1[1] - rgb2[1]) +
Math.abs(rgb1[2] - rgb2[2]);
};
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];
}
我有同样的问题,但我必须在PHP开发它。我用了@Garek的解决方案,我也用了这个答案: 转换十六进制颜色到RGB值在PHP转换十六进制颜色代码到RGB。
所以我要分享它。
我想在给定的背景颜色下使用这个函数,但不总是从“#”开始。
//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;
}
丑陋的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'
谢谢@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;
}