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

abe*_*nci 5 .net graphics bitmap

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

Random rand = new Random();

Color random = Color.FromArgb((int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255), 
                              (int)(rand.NextDouble() * 255));
Run Code Online (Sandbox Code Playgroud)

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

谢谢。

Chr*_*ris 5

理论

Full Saturation(由 HSL 和类似的配色方案使用)实际上意味着您有一个全 RGB 值,一个为 0,一个为任何其他值。

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

算法 1

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

  1. 生成 0 到 1 之间的随机数。
  2. 将此数字随机分配给 R、G 和 B 元素中的一个。
  3. 将零随机分配给剩余元素之一。
  4. 将最后一个元素设置为 1。

这将为您提供相对简单的最大饱和度颜色。

对于实现来说,最简单的方法是为 6 种可能的选择生成一个随机数 1 到 6,您将 0、1 和随机元素分配给哪个组件,然后使用某种开关。

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

算法2

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

  1. 为每个 R、G 和 B 分量生成随机值
  2. 找到最大分量。
  3. 找到最小组件。
  4. 将最大组件设置为 1。
  5. 将最小组件设置为 0。

这与将一个值设置为 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]);
Run Code Online (Sandbox Code Playgroud)

  • “这具有将 [...] 设置为随机值的相同效果”:这是错误的,因为您选择了最小和最大随机值,其余的 _在 0 和 1_ 之间没有平坦的随机分布。一个更简单正确的方法:设置 rgb[0] = 0, rgb[1] = 255 和 rgb[2] = random(256),然后随机打乱数组。 (2认同)