类似于计算rgb分量的平均值,然后决定使用黑色还是白色?
我是否必须先将RGB转换为HSV,因为RGB并不总是人眼看到的颜色?
我正在使用C#。
恰好我不久前在一个项目中需要这个函数。
private int PerceivedBrightness(Color c)
{
return (int)Math.Sqrt(
c.R * c.R * .241 +
c.G * c.G * .691 +
c.B * c.B * .068);
}
我在网上找到了这个公式,它来自于 Nbd Tech ,用于处理感知颜色和颜色转换公式。该网站提供了很多有用的信息。
使用此公式来选择黑色或白色的方法如下:
var foreColor = (PerceivedBrightness(backColor) > 130 ? Color.Black : Color.White);
您可以使用除130以外的值作为截止值,这是个人偏好。
我通过使用Photoshop玩耍得出的值实际上是0.241、0.691和0.068,但我后来得知值0.299、0.587和0.114更为准确。
此规范遵循ITU-R Recommendation BT.601(简称Rec. 601)。我上面提到的Nbd Tech网站尚未更新反映这一点。
基于此,以下是更新的方法 (感谢DTI-Matt的评论):
private int PerceivedBrightness(Color c)
{
return (int)Math.Sqrt(
c.R * c.R * .299 +
c.G * c.G * .587 +
c.B * c.B * .114);
}
关于阈值偏好的说明:
亮度在中间范围(例如120-140)的颜色会更加主观。例如,关于红色(FF0000),它的亮度为139,黑色或白色叠加效果更清晰存在争议。
R: .299
G: .587
B: .114
- DTI-MattColor.Red
(R 255,G 0,B 0),则根据上述值,它评估为感知亮度为139。我同意白底红字更好,但黑底并非不可读。在120-140范围内的值将更加主观。尝试使用各种颜色和阈值140查看是否适合您的目的。 - JYelton那方面怎么样?
private static Color GetReadableForeColor(Color c)
{
return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
Color
结构支持本地转换为 HSB。
if (Color.GetBrightness() > 0.5f) {
// win
}
你可以根据颜色深度进行简单的计算,例如如果你有一个 #FFFFFF 的颜色格式,你只需要将 RGB 值相加并计算它们是否低于一半。
在这种情况下,每个值的最大值为 255(F x F = 256),因此只需检查它是否低于该阈值:
var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";
如果颜色较暗,使用白色背景。如果颜色较亮,使用黑色背景。这并不完美,但是一个开始的想法。
这与问题直接无关(因为它没有提到Unity),但是对于其他使用Unity和UnityEngine.Color结构的读者来说,注意它们已经有一个属性可以利用来实现类似于这样的功能:{{link1:Color.grayscale
}},它返回一个范围为0-1的浮点数,与主要答案中提到的"PerceivedBrightness"函数类似(它使用相同的r*.299、g*.587、b*.114的值)。对于黑色/暗色,它将更接近0,而对于白色/亮色,它将更接近1。
这是我正在使用的基于Color.grayscale的函数:
// get most visible color between black & white for a given color (e.g to put text on a color)
public static Color GetReadableForeColor(Color bg) => bg.grayscale > 0.509f ? Color.black : Color.white;
如果我理解正确,一种方法可能是获取桌面壁纸图像,以某种方式检查其颜色,然后根据此更改应用程序颜色。
有一篇关于获取当前桌面壁纸的文章on geekpedia(在谷歌上有很多相关结果),但基本原理是获取当前壁纸的注册表值:
RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();
你可以使用该路径打开图像。然后,您可以获取许多属性,例如 RGB 中的尺寸和单个像素颜色。
要确定它是“更白”还是“更黑”,您有很多选择。
其中一个想法是获取 RGB 中的每个像素颜色,平均值(以获取灰度值),然后平均每个像素的灰度值。如果这个值大于 128,则可以被视为“白色”。如果小于 128,则为“黑色”。基本上,您正在决定图像像素强度的平均值在中灰分界线的哪一侧。
// Psudo code - can't check the C# spec atm.
foreach(Pixel p in image)
{
// get average of colour components.
double greyScale = (p.Red + p.Green + p.Blue) / 3;
totalIntensity += greyScale;
}
double averageImageIntensity = totalIntensity / image.NumPixels;
if(totalIntensity > 128) // image could be considered to be "white"
else // image could be considered "black".