[英]From a list of colors, how can I get a light or dark color that is visible over each color simultaneously?
在我的应用程序中,我允许用户最多选择三种颜色用作“主题颜色”。 这些颜色在状态栏下显示为LinearGradientBrush
(如果选择一种颜色,则显示为SolidColorBrush
)。 我需要状态栏前景色为浅色或深色(不一定只有黑色或白色)。 这将比仅确定应使用白色还是黑色要复杂得多,但是要包括深灰色(例如,如果用户选择主题使用白色和黑色,即是我目前的算法选择黑色作为前景,这是不可见的)之类的颜色。他们选择的黑色)。 另外, StatusBar.ForegroundColor
忽略Alpha通道,因此我不能只更改不透明度。 我怎样才能做到这一点?
谢谢
对比色可以通过HSB颜色的反色来确定
仅适用于黑白,您可以使用
ForeColor = BackColor.GetBrightness() > 0.4 ? Color.Black : Color.White;
您可以根据颜色的R,G和B值计算颜色的亮度,然后根据该值选择画笔。 我使用以下转换器选择与绑定的背景色形成对比的前景色。
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Color c = (Color)value;
int brightness = (int)(c.R * 0.30 + c.G * 0.59 + c.B * 0.11);
if (brightness < 127)
return App.Current.Resources["LightBrush"];
else
return App.Current.Resources["DarkBrush"];
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
我将其用于绑定到Colors类中所有已命名颜色的颜色选择器。 如果您仅针对几种主题色,则可以手工制作一张仍保持对比度的有色表,而不是将所有内容强制设置为黑白。
对于更多颜色,您可以尝试从RGB转换为HSL,在保持色相的同时修改亮度,然后再转换回去,但这可能比它值得的麻烦更多,并且在往返旅行时可能会用尽色域并获得较差的结果。
我玩了一些游戏,我认为我有一个完美的方法。 我从这个问题开始使用一种算法,然后将其与Matt Lacey和Rob Caplan的答案中的类似代码混合,将其清理并修改为可使用的颜色列表。 我认为效果很好。
private static Color DetermineForegroundColor(List<Color> colors) {
double r = 0, g = 0, b = 0;
foreach (Color color in colors) {
r += color.R;
g += color.G;
b += color.B;
}
if (r > g && r > b) {
Debug.WriteLine("First condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)r,
G = (byte)r,
B = (byte)r
};
}
else if (g > r && g > b) {
Debug.WriteLine("Second condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)g,
G = (byte)g,
B = (byte)g
};
}
else if (b > r && b > g) {
Debug.WriteLine("Third condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)b,
G = (byte)b,
B = (byte)b
};
}
else if (r == g) {
Debug.WriteLine("Fourth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)b,
G = (byte)b,
B = (byte)b
};
}
else if (r == b) {
Debug.WriteLine("Fifth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)g,
G = (byte)g,
B = (byte)g
};
}
else if (g == b) {
Debug.WriteLine("Sixth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)r,
G = (byte)r,
B = (byte)r
};
}
else {
Debug.WriteLine("No condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = 255,
G = 255,
B = 255
};
}
}
将来,我可能会用switch/case
块替换较大的if/else-if/else
块,以减少体积。
尝试以下任一方法:
要么
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.