根据背景将前景色设为黑色或白色
Posted
技术标签:
【中文标题】根据背景将前景色设为黑色或白色【英文标题】:Make foregroundcolor black or white depending on background 【发布时间】:2011-01-15 12:49:48 【问题描述】:类似于计算 rgb 分量的平均值,然后决定是使用黑色还是白色?
我是否必须在第一步将 RGB 转换为 HSV,因为 RGB 并不总是人眼所见?
我正在使用 C#
【问题讨论】:
这个问题包含可以帮助你的答案:***.com/questions/946544/… 相关(但自欺欺人):***.com/questions/3116260/…***.com/questions/3942878/… 【参考方案1】:恰好我不久前的一个项目需要这个功能。
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 以外的值作为截止值;这是偏好。
更新:据 his site 的 Darel Rex Finley 所说:
我通过使用 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)与黑色或白色叠加层是否更清晰是有争议的。
【讨论】:
这基本上是亮度的公式,对值进行平方以赋予异常值更多权重。结果是 0-255 的比例。 en.wikipedia.org/wiki/Luma_%28video%29 注意: 这些值的来源已更新:alienryderflex.com/hsp.html 它们现在显示为:R: .299
G: .587
B: .114
“红色”怎么会变成“浅”色。红底黑字不好看。
@Simon 如果您的意思是Color.Red
(R 255, G 0, B 0),它会根据上述值评估感知亮度 139。我同意红底白字更可取,但黑色并非不可读。 120-140 范围内的值会更主观。尝试各种颜色的阈值 140,看看它是否适合您的目的。【参考方案2】:
Color
结构本身支持转换为 HSB。
if (Color.GetBrightness() > 0.5f)
// win
您可能还想添加饱和度组件,因为饱和度也有助于明显的“亮度”。
【讨论】:
【参考方案3】:那又怎样?
private static Color GetReadableForeColor(Color c)
return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
【讨论】:
尝试使用以下值:128、255、0。它是浅绿色,在黑色背景下更易于阅读。但是,平均值为 127,您的方法将返回白色。 在我尝试过的所有解决方案中,这是给我最好的结果的一个,无论是在视觉上还是在以编程方式确定两种颜色范围之间的对比度时。 +1。【参考方案4】:如果我理解正确,一种方法可能是获取桌面壁纸图像,检查一些庄园它是什么颜色,然后根据它更改您的应用程序颜色。
有一篇文章on geekpedia 是关于获取当前桌面壁纸(以及google 上的大量点击),但基本前提是获取当前壁纸的注册表值:
RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();
然后您可以使用该路径打开图像。然后,您可以获得许多属性,例如 RGB 中的尺寸和单个像素颜色。
要确定是“更白”还是“更黑”,您有很多选择。
一个想法是获取 RGB 中的每个像素颜色,平均这些值(以获取灰度值),然后平均整个图像中每个像素的灰度值。如果结果 > 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".
问题:可能是一个缓慢的过程,您可能只想对一些像素进行采样(例如,每 10 个像素等)以节省时间。更一般地说,这似乎是一件相当老套的事情。在运行时拉取用户文件并弄乱它们很难干净,并且它提供了潜在的安全性和稳定性问题。如果图像是 duff 或损坏等怎么办?
我个人建议只是让用户自己选择颜色/主题/皮肤,或者更好的是让他们自定义!
【讨论】:
我不想改变整个应用的颜色。我正在使用一个列表视图,其中项目具有 bg 颜色,并且每个项目的文本应该是可读的......【参考方案5】:您可以根据颜色深度进行简单的计算,如果说您有 #FFFFFF 颜色格式,您可以添加 RGB 值并计算它们是否在一半以下。
这种情况下的最大值是 255 (F x F = 256) per,所以只需检查它是否低于该阈值:
var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";
如果颜色在下方,则颜色较深...使用白色背景。如果它在上面,它更轻......使用黑色背景。它并不完美,但可以作为一个开始的想法。
【讨论】:
我最初在我的项目中尝试过类似的方法,但结果是在某些情况下,白色/黑色标签在其背景颜色中不那么明显。以上是关于根据背景将前景色设为黑色或白色的主要内容,如果未能解决你的问题,请参考以下文章