【问题标题】:Generate a specific color for each string?为每个字符串生成特定的颜色?
【发布时间】:2010-08-30 21:21:36
【问题描述】:

我有一个显示属于产品的订单的 DataGrid。

我想要一个生成的SolidColorBrush 对每个产品都是唯一的。

更新

我需要这些颜色是纯色和独特的,或者至少以独特的方式排序,即不应该有黑色、蓝色、绿色,因为这 3 种颜色可能会相互混淆。此外它应该是黑色,红色,蓝色等。

公式必须是:

  1. 将所有颜色分组为主要颜色的子组
  2. 按黑暗顺序排列
  3. 与前一组再次按乒乓交替方式(暗光暗光等)排序。
  4. 我刚刚注意到有一个很酷的功能:Color.AreClose,它可能很有用,我仍然不知道如何实现它。
  5. 我相信你有更多的想法。

相关:Is there a .NET list of 256 colors only?

【问题讨论】:

  • 颜色一定要好看吗?
  • 不,只是颜色。 SolidColorBrush。

标签: wpf colors


【解决方案1】:

你可以创建一个函数,根据某种种子返回颜色。然后只需在 xaml 中绑定项目背景色。例如,种子可以只是一个普通字节,它将采用 R(RGB)并加上 +10。问题是您需要提供更多信息。就像 akellehe 询问颜色是否必须看起来不错,两个彼此接近的项目是否需要两种真正不同的颜色或类似的东西会做(例如 RGB (128,128,128) 和 (128,128,129) )。还有可以有多少项?

【讨论】:

【解决方案2】:

根据色相、饱和度和值来考虑颜色可能会有所帮助。现在,您可以考虑使用 Hue 和 Value 中的不同采样函数来生成颜色。例如,您可能会增加色调,然后以不同的值重复以获得相同颜色的较暗版本。您还可以在交替的值位置偏移您的色调,以获得额外的颜色可变性。为获得最佳效果,您可能希望在采样期间交替使用“暖色”和“冷色”(喜欢红色与喜欢蓝色)。


编辑:

有关 Hue 的技术概述,请参阅 this article 以了解 HSV RGB 的转换。它们有点尴尬,因为 HSV 通常被解释为一个圆锥体,色调被视为围绕法线轴的角度。它是这样构造的,因为一旦达到 V=0,色调和饱和度都是未定义的(基本上,黑色是黑色;它没有色调;灰色(垂直轴)也没有色调)为了您的目的,您可以简单地使用方程式(请参阅“色调和色度”和“转换为 RGB”部分)。

实施 HSV 转换后,最简单的纯色相变化的颜色采样是从 0 到 360/(N-1) 取色相,其中 N 是样本数。您可以随意设置饱和度和值; S=1 和 V=1 将为您提供最明亮、最“多彩”(饱和)的颜色。如果您有太多的点无法简单地在色调中采样,您可以开始将其与值(用于较暗的颜色)或饱和度(用于更不饱和的“灰色”颜色)的变化结合起来。

【讨论】:

  • +1。我用其他语言做过类似的事情,HSB 是要走的路。 Hue 是一个 360 度色轮,很容易除以给定数据所需的确切颜色数量 - 提前创建 50 种颜色并选择 7 种颜色比仅将可用颜色空间划分为 7 种要困难得多。跨度>
  • 听起来不错。我从来没有处理过色调,您能否添加一个示例来创建基于色调除以计数的随机颜色列表:Color GetColors(int count)
【解决方案3】:

在 W3C 网站的工作草案中建议了一个粗略的color difference formula

色差由 下面的公式:(最大值(红色值 1、红色值 2) - 最小值(红色值 1, 红色值 2)) + (最大值(绿色 值 1,绿色值 2) - 最小值 (绿色值 1,绿色值 2)) + (最大值(蓝色值 1,蓝色值 2) - 最小值(蓝色值 1,蓝色值 2))

颜色亮度的范围[n]ge 差为 125。颜色的范围 相差500。

您可能还需要其他 more complex ones 以获得最佳结果。

然后,您可以在算法中使用该函数,该算法将所有可能的颜色存储在一组中,从该组中选择一种颜色(例如黑色),并将其用作迭代排序的起点。

这既没有经过优化也没有经过测试,但它可能会起作用:

static List<Color> SortColors(IEnumerable<Color> colors)
{
    var hashed = new HashSet<Color>(colors);
    var sorted = new List<Color>(hashed.Count);

    //Start with black
    var last = hashed.Single(x => x.Red == 0 && x.Green == 0 && x.Blue == 0);
    hashed.Remove(last);
    sorted.Add(last);

    while (hashed.Any())
    {
        //This could of course be optimized by doing these two steps in a single loop
        var bestDiff = hashed
            .Max(x => Difference(x, last));
        var best = hashed.First(x => Difference(x, last) == bestDiff);

        hashed.Remove(best);
        sorted.Add(best);
        last = best;
    }

    return sorted;
}

static int Difference(Color a, Color b)
{
    return Math.Abs(a.Red - b.Red)
        + Math.Abs(a.Green - b.Green)
        + Math.Abs(a.Blue - b.Blue);
}

【讨论】:

  • +1,看起来不错,但是我应该为颜色 arg 提供什么?我只想提供一个 int 指定返回多少颜色。我也希望开始颜色是随机的。
  • 可能是一个已解析的调色板——也许您可以使用反射来获取 System.Windows.Media.Colors 中所有属性的列表。要随机化它,您只需使用 Random 在随机索引处为最后一个选择第一个值:var last = hashed.ElementAt(new Random().Next(hashed.Count - 1));
  • 您可以将其用于参数:var colors = typeof(Colors).GetProperties().Select(p =&gt; (Color)p.GetValue(null, null));
  • 但我不明白为什么我必须提供一个值而不是使用 count int 参数,并对其进行迭代,在每次迭代时创建新颜色?
  • 在给定整个 24 位光谱的情况下,可能有一种算法方法可以从另一个颜色中找到最远的感知颜色,然后找到中点,然后再找到最远的颜色等,但我想它非常复杂。我当然不知道它的数学。我认为这就是为什么您在另一个线程中寻找 256 调色板的原因;对不起,我误解了。无论哪种方式,如果数百种颜色都以笨拙的渐变排列,人眼可以轻松区分它们,但大多数人不会记得有数百种颜色在其他地方重复出现。
【解决方案4】:

最适合我:

Private Shared ReadOnly rndm As New Random
Public Shared ReadOnly m_ColorsList As IEnumerable(Of Color) =
  Enumerable.Range(0, 100).Select(
    Function(i) Color.FromRgb(rndm.Next(256), rndm.Next(256), rndm.Next(256)))

将数字 100 替换为所需的颜色数量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-19
    • 2010-12-16
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    相关资源
    最近更新 更多