从颜色列表中,如何获得同时在每种颜色上可见的浅色或深色?

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 块,以使其不那么笨重。