给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
当前回答
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;
};
其他回答
一个Android版本,捕捉alpha以及。
(感谢@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);
}
我也遇到过类似的问题。我必须找到一种选择对比字体颜色的好方法,以便在色度/热图上显示文本标签。它必须是通用的方法,生成的颜色必须“好看”,这意味着简单地生成互补色并不是一个好的解决方案——有时它会生成奇怪的、非常强烈的颜色,很难观察和阅读。
经过长时间的测试和尝试解决这个问题,我发现最好的解决方案是选择白色字体的“深色”,和黑色字体的“明亮”的颜色。
下面是我在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/
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
}
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是一个更好的查询测试平台
请注意,在谷歌闭包库中有一个算法,该算法引用了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]);
};