如何随机生成完全饱和的颜色?
我通常使用下面的代码来生成随机颜色:如何随机生成完全饱和的颜色?
Random rand = new Random();
Color random = Color.FromArgb((int)(rand.NextDouble() * 255),
(int)(rand.NextDouble() * 255),
(int)(rand.NextDouble() * 255));
但大多看起来像一个灰色的变化。我怎样才能限制输出只有完全饱和的颜色?
谢谢。
理论
完全饱和(13759 HSL和类似的配色方案),实际上意味着,你必须在一个完整的RGB值,一个0,一个在任何其他值。
其原因是饱和度是基于最高和最低颜色成分之间的差异,并且当它们处于极端时是最高的。实际的定义更加复杂(并涉及亮度),但足够说一个0和另一个1的分量将给出最大饱和度。
算法1
这导致这样做的一个比较简单的方法。
- 生成随机数0和1之间 随机
- 分配这个号码到一个FO的R,G和B的元素。
- 将零随机分配给其余元素之一。
- 设定的最后一个元素为1
这会给你一个最大饱和度的颜色相对简单。
对于实现它可能是最容易产生一个随机数1到6为6可能的选择你分配0,1和随机元素,然后使用某种类型的开关。
这是最简单的算法,但由于选择/分支不一定是最简单的实现。
算法2
的建议由吉姆·米契尔基于类似的理论,但只是实现了一个稍微不同的第二种方法。
- 产生用于每个R,G和B分量
- 的随机值查找最大分量。
- 找到最小组件。
- 将最大分量设置为1.
- 将最小分量设置为0。
这与将一个值设置为1,一个设置为0和一个设置为随机值的效果相同。它的优点是它不需要你使用凌乱的switch语句,但是你最终可能会产生一些混乱的循环。同样取决于你的组件的精度(例如,如果你直接用字节),那么如果你的中间值实际上等于你的顶部或底部(或所有三个都是相同的),那么这可能也会被重置,这取决于你如何编码你的算法。这将主要影响随机性的倾斜,但这不太可能引人注意。吉姆
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]);
的方法,两人还礼貌为了记录
代码实现,这里是一个小的适应吉姆·米契尔建议(下面是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个值中随机:
- ö ne到0x80
- 另一个0xFF
- 剩余的一个到0X80到0xFF之间的一个随机值。
随机值与的0x10的步骤产生得到一组不同颜色的减少(即6×8 = 48),则可以写为arr[2] = r.nextInt(0x80) + 0x80;
更多的选择。
我也将最小值设置为0x80以获得饱和度较低的颜色,这在我看来更好看一些(这是一个不好的味道......)。你可以减少这个最小值来增加饱和度。
表达式'(int)(rand.NextDouble()* 255)'永远不会生成值“255”。 'NextDouble'生成一个数字,使得0
很高兴知道,吉姆 – abenci