(Java示例)
public Color generateRandomColor(Color mix) {
Random random = new Random();
int red = random.nextInt(256);
int green = random.nextInt(256);
int blue = random.nextInt(256);
// mix the color
if (mix != null) {
red = (red + mix.getRed()) / 2;
green = (green + mix.getGreen()) / 2;
blue = (blue + mix.getBlue()) / 2;
}
Color color = new Color(red, green, blue);
return color;
}
进一步地,你可以为你的生成器添加启发式算法,考虑到互补颜色或阴影层次,但这完全取决于你想要通过随机颜色实现的印象。
一些额外的资源:
我会使用色轮,并在随机位置添加黄金角度(137.5度)(Golden Angle),以便每次获得不重叠的不同颜色。
通过调整色轮的亮度,您还可以获得不同的明/暗颜色组合。
我发现这篇博客文章非常好地解释了使用黄金比例解决问题的方法和解决方案。
(http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/)
更新:我刚刚发现了另一种方法:
它被称为RYB(红、黄、蓝)方法,并在这篇论文中描述:(http://threekings.tk/mirror/ryb_TR.pdf),作为“绘画启发式颜色合成”。该算法生成颜色,并选择每个新颜色以最大化其与先前选择的颜色之间的欧几里得距离。
在这里,您可以找到javascript的良好实现:
(http://afriggeri.github.com/RYB/)
更新2:
Sciences Po Medialb刚刚发布了一个名为“I want Hue”的工具,为数据科学家生成颜色调色板。使用不同的颜色空间,并通过使用k-means聚类或力向量(排斥图)生成调色板。这些方法的结果非常好,他们在其网页上展示了理论和实现。
这是一个网站链接,可以用于生成配色方案。function pastelColors(){
var r = (Math.round(Math.random()* 127) + 127).toString(16);
var g = (Math.round(Math.random()* 127) + 127).toString(16);
var b = (Math.round(Math.random()* 127) + 127).toString(16);
return '#' + r + g + b;
}
在这里看到了这个想法:http://blog.functionalfun.net/2008/07/random-pastel-colour-generator.html
转换到另一个调色板是更优秀的方式。他们这样做是有原因的:其他调色板是“感知”的——也就是说,它们将看起来相似的颜色放在一起,而且调整其中一个变量会以可预测的方式改变颜色。在RGB中,所有这些都不成立,因为没有明显的关系可以让颜色“搭配得好”。
我使用 TriadMixing 和 CIE94 成功避免了相似的颜色。下面的图片使用了红、黄和白三种颜色。请看这里。
// http://devmag.org.za/2012/07/29/how-to-choose-colours-procedurally-algorithms/#:~:text=120%20and%20240.-,7.%20Triad%20Mixing,-This%20algorithm%20takes
public static Color RandomMix(Color color1, Color color2, Color color3,
float greyControl)
{
int randomIndex = random.NextByte() % 3;
float mixRatio1 =
(randomIndex == 0) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio2 =
(randomIndex == 1) ? random.NextFloat() * greyControl : random.NextFloat();
float mixRatio3 =
(randomIndex == 2) ? random.NextFloat() * greyControl : random.NextFloat();
float sum = mixRatio1 + mixRatio2 + mixRatio3;
mixRatio1 /= sum;
mixRatio2 /= sum;
mixRatio3 /= sum;
return Color.FromArgb(
255,
(byte)(mixRatio1 * color1.R + mixRatio2 * color2.R + mixRatio3 * color3.R),
(byte)(mixRatio1 * color1.G + mixRatio2 * color2.G + mixRatio3 * color3.G),
(byte)(mixRatio1 * color1.B + mixRatio2 * color2.B + mixRatio3 * color3.B));
}
这是一个不可忽视的答案,因为它简单易懂且具有优势。那就是采样现实生活中的照片和绘画。随机采样现代艺术图片、塞尚、梵高、莫奈、照片等缩略图上的任意像素,以获得任意数量的随机颜色。其优点是可以按主题获取颜色,而且它们是有机的颜色。只需将 20-30 张图片放入文件夹中,每次随机抽取一张即可。
转换为HSV值是一种基于心理学的调色板常见的代码算法。hsv 更容易随机化。
function pastelColors() {
$r = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
$g = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
$b = dechex(round(((float) rand() / (float) getrandmax()) * 127) + 127);
return "#" . $r . $g . $b;
}
来源: https://dev59.com/mHVD5IYBdhLWcg3wO5ED#12266311
在Java中,您可以使用以下代码获取当前时间的毫秒数:long currentTimeMillis = System.currentTimeMillis();
这将返回自1970年1月1日00:00:00 GMT以来经过的毫秒数。David Crow的R语言两行代码方法:
GetRandomColours <- function(num.of.colours, color.to.mix=c(1,1,1)) {
return(rgb((matrix(runif(num.of.colours*3), nrow=num.of.colours)*color.to.mix)/2))
}
这是一个在C#中快速而简单的颜色生成器(使用本文章中描述的“RYB方法”)。它是从JavaScript重写而来。
用法:
List<Color> ColorPalette = ColorGenerator.Generate(30).ToList();
前两种颜色通常是白色和黑色的一种。我经常这样跳过它们(使用Linq):
List<Color> ColorsPalette = ColorGenerator
.Generate(30)
.Skip(2) // skip white and black
.ToList();
实现:
public static class ColorGenerator
{
// RYB color space
private static class RYB
{
private static readonly double[] White = { 1, 1, 1 };
private static readonly double[] Red = { 1, 0, 0 };
private static readonly double[] Yellow = { 1, 1, 0 };
private static readonly double[] Blue = { 0.163, 0.373, 0.6 };
private static readonly double[] Violet = { 0.5, 0, 0.5 };
private static readonly double[] Green = { 0, 0.66, 0.2 };
private static readonly double[] Orange = { 1, 0.5, 0 };
private static readonly double[] Black = { 0.2, 0.094, 0.0 };
public static double[] ToRgb(double r, double y, double b)
{
var rgb = new double[3];
for (int i = 0; i < 3; i++)
{
rgb[i] = White[i] * (1.0 - r) * (1.0 - b) * (1.0 - y) +
Red[i] * r * (1.0 - b) * (1.0 - y) +
Blue[i] * (1.0 - r) * b * (1.0 - y) +
Violet[i] * r * b * (1.0 - y) +
Yellow[i] * (1.0 - r) * (1.0 - b) * y +
Orange[i] * r * (1.0 - b) * y +
Green[i] * (1.0 - r) * b * y +
Black[i] * r * b * y;
}
return rgb;
}
}
private class Points : IEnumerable<double[]>
{
private readonly int pointsCount;
private double[] picked;
private int pickedCount;
private readonly List<double[]> points = new List<double[]>();
public Points(int count)
{
pointsCount = count;
}
private void Generate()
{
points.Clear();
var numBase = (int)Math.Ceiling(Math.Pow(pointsCount, 1.0 / 3.0));
var ceil = (int)Math.Pow(numBase, 3.0);
for (int i = 0; i < ceil; i++)
{
points.Add(new[]
{
Math.Floor(i/(double)(numBase*numBase))/ (numBase - 1.0),
Math.Floor((i/(double)numBase) % numBase)/ (numBase - 1.0),
Math.Floor((double)(i % numBase))/ (numBase - 1.0),
});
}
}
private double Distance(double[] p1)
{
double distance = 0;
for (int i = 0; i < 3; i++)
{
distance += Math.Pow(p1[i] - picked[i], 2.0);
}
return distance;
}
private double[] Pick()
{
if (picked == null)
{
picked = points[0];
points.RemoveAt(0);
pickedCount = 1;
return picked;
}
var d1 = Distance(points[0]);
int i1 = 0, i2 = 0;
foreach (var point in points)
{
var d2 = Distance(point);
if (d1 < d2)
{
i1 = i2;
d1 = d2;
}
i2 += 1;
}
var pick = points[i1];
points.RemoveAt(i1);
for (int i = 0; i < 3; i++)
{
picked[i] = (pickedCount * picked[i] + pick[i]) / (pickedCount + 1.0);
}
pickedCount += 1;
return pick;
}
public IEnumerator<double[]> GetEnumerator()
{
Generate();
for (int i = 0; i < pointsCount; i++)
{
yield return Pick();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static IEnumerable<Color> Generate(int numOfColors)
{
var points = new Points(numOfColors);
foreach (var point in points)
{
var rgb = RYB.ToRgb(point[0], point[1], point[2]);
yield return Color.FromArgb(
(int)Math.Floor(255 * rgb[0]),
(int)Math.Floor(255 * rgb[1]),
(int)Math.Floor(255 * rgb[2]));
}
}
}