如何随机生成完全饱和的颜色?

时间:2011-12-12 15:41:05

标签: .net graphics bitmap

我通常使用以下代码生成随机颜色:

Random rand = new Random();

Color random = Color.FromArgb((int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255));

但他们中的大多数看起来像灰色的变化。如何将输出限制为仅完全饱和的颜色?

感谢。

3 个答案:

答案 0 :(得分:4)

<强>理论

完全饱和度(由HSL和类似颜色方案使用)实际上意味着您有一个RGB值,一个在0,一个在任何其他值。

原因是饱和度基于最高和最低颜色分量之间的差异,并且当它们处于极值时最高。实际的定义更复杂(并且涉及亮度)但是足以说0和1的另一个分量将给出最大饱和度。

算法1

这导致了一种相对简单的方法。

  1. 生成介于0和1之间的随机数。
  2. 将此数字随机分配给R,G和B元素中的一个。
  3. 随机将零分配给其余元素之一。
  4. 将最终元素设置为1。
  5. 这将相对简单地为您提供最大饱和度颜色。

    对于实现,最简单的方法是为您分配0,1和随机元素的6个可能选项生成随机数1到6,然后使用某种类型的开关。

    这是最简单的算法,但由于选择/分支,不一定是最简单的实现。

    算法2

    Jim Mischel基于类似理论提出的第二种方法,但实施方式略有不同。

    1. 为每个R,G和B组件生成随机值
    2. 找到最大组件。
    3. 找到min组件。
    4. 将最大组件设置为1。
    5. 将最小分量设为0。
    6. 这与将一个值设置为1,一个设置为0,一个设置为随机值具有相同的效果。它的优点是它不需要你使用凌乱的switch语句,但你最终可能会遇到一些混乱的循环。同样取决于组件的精度(例如,如果你直接使用字节),那么如果你的中间值实际上等于你的顶部或底部(或者所有三个是相同的)那么这可能也会被重置,这取决于你的编码方式你的算法。这主要会产生随机性偏差的影响,但这不太可能引人注意。

      方法二的代码实现也由Jim提供

          int[] rgb = new int[3];
          rgb[0] = rnd.Next(256);  // red
          rgb[1] = rnd.Next(256);  // green
          rgb[2] = rnd.Next(256);  // blue
      
          // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]);
      
          // find max and min indexes.
          int max, min;
      
          if (rgb[0] > rgb[1])
          {
              max = (rgb[0] > rgb[2]) ? 0 : 2
              min = (rgb[1] < rgb[2]) ? 1 : 2;
          }
          else
          {
              max = (rgb[1] > rgb[2]) ? 1 : 2;
              int notmax = 1 + max % 2;
              min = (rgb[0] < rgb[notmax]) ? 0 : notmax;
          }
          rgb[max] = 255;
          rgb[min] = 0;
      
          // Console.WriteLine("{0},{1},{2}", rgb[0], rgb[1], rgb[2]);
      

答案 1 :(得分:2)

我想你想用HSL值生成颜色,将饱和度固定为它的最大值,并且只将颜色和亮度随机化。您可以找到HSL颜色here的类。

答案 2 :(得分:0)

为了记录,这里是对 Jim Mischel 建议的一个小改编(下面是Java代码,对.net的改编是微不足道的):

private static Random r = new Random();

public static final String randomColor() {
    int[] arr = new int[3];
    arr[0] = 0x80;
    arr[1] = 0xFF;
    arr[2] = r.nextInt(0x10) * 8 + 0x80;
    // Fisher–Yates shuffle
    for (int i1 = arr.length - 1; i1 >= 0; i1--) {
        int i2 = r.nextInt(i1 + 1);
        int tmp = arr[i2];
        arr[i2] = arr[i1];
        arr[i1] = tmp;
    }
    return String.format("%02x%02x%02x", arr[0], arr[1], arr[2]);
}

我们随机设置3个值:

  • 一到0x80
  • 另一个为0xFF
  • 剩下的一个到0X80和0xFF之间的随机值。

随机值的生成步长为0x10,以获得一组不同颜色(即6 x 8 = 48),您可以编写arr[2] = r.nextInt(0x80) + 0x80;以获得更多选择。

我还将最小值设置为0x80以获得较少饱和的颜色,这在我看来更好看(这是一个不好的味道......)。您可以降低此最小值以增加饱和度。