从颜色列表中,如何获得同时在每种颜色上可见的浅色或深色?
From a list of colors, how can I get a light or dark color that is visible over each color simultaneously?
在我的应用中,我允许用户选择最多三种颜色作为 'theme color'。这些颜色在状态栏下显示为 LinearGradientBrush
(或 SolidColorBrush
,如果选择了一种颜色)。我需要浅色或深色(不一定 仅 黑色或白色)作为状态栏前景色。这将比仅确定是否应使用白色或黑色更复杂,但包括深灰色等颜色(即,如果用户选择白色和黑色作为他们的主题,我当前的算法选择黑色作为无法看到的前景他们选择的黑色)。另外,StatusBar.ForegroundColor
忽略了 alpha 通道,所以我不能只改变不透明度。我该怎么做?
谢谢
试试看:
- 反转每个 RGB 值,然后可能调整到一组预定义颜色中最接近的颜色。
或
- OR 将 RGB 的每个值乘以给定的数量(比如 .25 - .5)。如果 > 128 相乘然后相减两次,如果 < 128 就相乘。
对比色可以通过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();
}
}
我将其用于颜色选择器,该颜色选择器绑定到颜色 class 中的所有命名颜色。如果您只针对几种主题颜色,那么您可以手工制作 table 仍然保持对比度的有色颜色,而不是将所有内容都强制为黑色和白色。
对于更多颜色,您可以尝试从 RGB 转换为 HSL,在保持色相的同时修改亮度,然后再转换回来,但这可能比它的价值更麻烦,您可以 运行 超出色域而往返并得到糟糕的结果。
几年前I created something for a similar problem such that given a color it would return the color that is opposite it on the color wheel。
我用它创建了第二个或免费的颜色画笔,用于在我想要的不仅仅是单一的、用户选择的、系统范围的强调颜色的应用程序中,而是希望确保这些颜色可以一起工作,而不是冲突。
也许你可以将这个想法扩展到三种颜色。
代码在 GitHub: https://github.com/mrlacey/WPMisc/blob/master/AccentComplimentBrush.cs
我做了一些尝试,我认为我找到了一个完美的方法。我从 this question 中的一个算法开始,并将其与 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
块,以使其不那么笨重。
在我的应用中,我允许用户选择最多三种颜色作为 'theme color'。这些颜色在状态栏下显示为 LinearGradientBrush
(或 SolidColorBrush
,如果选择了一种颜色)。我需要浅色或深色(不一定 仅 黑色或白色)作为状态栏前景色。这将比仅确定是否应使用白色或黑色更复杂,但包括深灰色等颜色(即,如果用户选择白色和黑色作为他们的主题,我当前的算法选择黑色作为无法看到的前景他们选择的黑色)。另外,StatusBar.ForegroundColor
忽略了 alpha 通道,所以我不能只改变不透明度。我该怎么做?
谢谢
试试看:
- 反转每个 RGB 值,然后可能调整到一组预定义颜色中最接近的颜色。
或
- OR 将 RGB 的每个值乘以给定的数量(比如 .25 - .5)。如果 > 128 相乘然后相减两次,如果 < 128 就相乘。
对比色可以通过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();
}
}
我将其用于颜色选择器,该颜色选择器绑定到颜色 class 中的所有命名颜色。如果您只针对几种主题颜色,那么您可以手工制作 table 仍然保持对比度的有色颜色,而不是将所有内容都强制为黑色和白色。
对于更多颜色,您可以尝试从 RGB 转换为 HSL,在保持色相的同时修改亮度,然后再转换回来,但这可能比它的价值更麻烦,您可以 运行 超出色域而往返并得到糟糕的结果。
几年前I created something for a similar problem such that given a color it would return the color that is opposite it on the color wheel。
我用它创建了第二个或免费的颜色画笔,用于在我想要的不仅仅是单一的、用户选择的、系统范围的强调颜色的应用程序中,而是希望确保这些颜色可以一起工作,而不是冲突。
也许你可以将这个想法扩展到三种颜色。
代码在 GitHub: https://github.com/mrlacey/WPMisc/blob/master/AccentComplimentBrush.cs
我做了一些尝试,我认为我找到了一个完美的方法。我从 this question 中的一个算法开始,并将其与 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
块,以使其不那么笨重。