题
我正在寻找一种简单的算法来生成大量随机的、美观的颜色。所以不要有疯狂的霓虹色、让人想起粪便的颜色等。
我已经找到了这个问题的解决方案,但它们依赖于 RGB 以外的替代调色板。我宁愿直接使用 RGB 而不是来回映射。这些其他解决方案也最多只能生成 32 种左右令人愉悦的随机颜色。
任何想法都会很棒。
解决方案
您可以将随机颜色的 RGB 值与恒定颜色的 RGB 值进行平均:
(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;
}
将随机颜色与白色(255、255、255)混合,通过增加亮度同时保持原始颜色的色调来创建中性粉彩。这些随机生成的粉彩通常可以很好地搭配在一起,尤其是数量较多时。
以下是使用上述方法生成的一些柔和的颜色:
您还可以将随机颜色与恒定的柔和颜色混合,从而产生一组有色的中性颜色。例如,使用浅蓝色可创建如下颜色:
更进一步,您可以在生成器中添加启发式算法,考虑互补色或阴影级别,但这完全取决于您想要通过随机颜色实现的印象。
一些额外的资源:
其他提示
我会使用色轮并给定一个随机位置,您可以添加黄金角度(137,5 度)
http://en.wikipedia.org/wiki/Golden_angle
为了每次得到不重叠的不同颜色。
调整色轮的亮度,您还可以获得不同的亮/暗颜色组合。
我发现这篇博客文章很好地解释了这个问题以及使用黄金比例的解决方案。
http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
更新: 我刚刚发现了另一种方法:
它称为 RYB(红、黄、蓝)方法,在本文中进行了描述:
http://trikings.tk/mirror/ryb_TR.pdf
作为“绘画启发的色彩合成”。
该算法生成颜色,并选择每种新颜色以最大化其与先前选择的颜色的欧几里得距离。
在这里你可以找到一个很好的 javascript 实现:
http://afriggeri.github.com/RYB/
更新2:
Science Po Medialb 刚刚发布了一款名为“I Want Hue”的工具,可以为数据科学家生成调色板。使用不同的颜色空间并使用 k 均值聚类或力向量(斥力图)生成调色板 这些方法的结果非常好,他们在网页中展示了理论和实现。
在 JavaScript 中:
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.functionfun.net/2008/07/random-pastel-colour-generator.html
转换为另一个调色板是一种更好的方法。他们这样做是有原因的:其他调色板是“感知的”——也就是说,它们将看起来相似的颜色放在一起,调整一个变量会以可预测的方式改变颜色。对于 RGB 来说,这一切都不是这样,“搭配得很好”的颜色之间没有明显的关系。
一个不容忽视的答案是对现实生活中的照片和绘画进行采样,因为它既简单又具有优势。在现代艺术图片、塞尚、梵高、莫内、照片的缩略图上采样任意数量的随机像素和随机颜色...优点是您可以按主题获取颜色,并且它们是有机颜色。只需将 20 - 30 张照片放入一个文件夹中,然后每次随机抽取一张随机图片。
转换为 HSV 值是基于心理的调色板的一种广泛的代码算法。hsv 更容易随机化。
在 PHP 中:
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;
}
这是 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]));
}
}
}
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))
}
function fnGetRandomColour(iDarkLuma, iLightLuma)
{
for (var i=0;i<20;i++)
{
var sColour = ('ffffff' + Math.floor(Math.random() * 0xFFFFFF).toString(16)).substr(-6);
var rgb = parseInt(sColour, 16); // convert rrggbb to decimal
var r = (rgb >> 16) & 0xff; // extract red
var g = (rgb >> 8) & 0xff; // extract green
var b = (rgb >> 0) & 0xff; // extract blue
var iLuma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709
if (iLuma > iDarkLuma && iLuma < iLightLuma) return sColour;
}
return sColour;
}
对于柔和的颜色,传递更高的亮度暗/亮整数 - 即 fnGetRandomColour(120, 250)
学分:所有学分都归于 http://paulirish.com/2009/random-hex-color-code-snippets/stackoverflow.com/questions/12043187/如何检查十六进制颜色是否太黑
JavaScript 改编自 David Crow 的原始答案,包括 IE 和 Nodejs 特定代码。
generateRandomComplementaryColor = function(r, g, b){
//--- JavaScript code
var red = Math.floor((Math.random() * 256));
var green = Math.floor((Math.random() * 256));
var blue = Math.floor((Math.random() * 256));
//---
//--- Extra check for Internet Explorers, its Math.random is not random enough.
if(!/MSIE 9/i.test(navigator.userAgent) && !/MSIE 10/i.test(navigator.userAgent) && !/rv:11.0/i.test(navigator.userAgent)){
red = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
green = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
blue = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))[0]) * 256));
};
//---
//--- nodejs code
/*
crypto = Npm.require('crypto');
red = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
green = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
blue = Math.floor((parseInt(crypto.randomBytes(8).toString('hex'), 16)) * 1.0e-19 * 256);
*/
//---
red = (red + r)/2;
green = (green + g)/2;
blue = (blue + b)/2;
return 'rgb(' + Math.floor(red) + ', ' + Math.floor(green) + ', ' + Math.floor(blue) + ')';
}
使用以下命令运行该函数:
generateRandomComplementaryColor(240, 240, 240);
你可以让它们处于一定的亮度范围内。这将稍微控制“霓虹灯”颜色的数量。例如,如果“亮度”
brightness = sqrt(R^2+G^2+B^2)
如果在一定的上限内,它就会呈现出褪色的浅色。相反,如果在某个下限内,则颜色会更暗。这将消除任何疯狂的、突出的颜色,如果你选择一个非常高或非常低的界限,它们都会相当接近白色或黑色。
通过算法很难得到你想要的东西——人们已经研究颜色理论很长时间了,他们甚至不知道所有的规则。
然而,有 一些 您可以使用这些规则来剔除不良颜色组合(即存在冲突颜色和选择互补色的规则)。
我建议您在尝试制作颜色之前访问图书馆的艺术部分并查看有关颜色理论的书籍,以便更好地了解什么是好颜色 - 看来您甚至可能不知道为什么某些组合有效而其他组合无效。 t。
-亚当
我强烈建议使用 CG HSVtoRGB 着色器函数,它们非常棒......它为您提供像画家一样自然的色彩控制,而不是像 CRT 显示器那样的控制,而您可能不是这样的!
这是一种生成 1 个浮点值的方法。IE。灰色,分为 1000 种颜色、亮度和饱和度等组合:
int rand = a global color randomizer that you can control by script/ by a crossfader etc.
float h = perlin(grey,23.3*rand)
float s = perlin(grey,54,4*rand)
float v = perlin(grey,12.6*rand)
Return float4 HSVtoRGB(h,s,v);
结果是很棒的颜色随机化!它不是自然的,但它使用自然的颜色渐变,它看起来有机且可控的虹彩/柔和的参数。
对于 perlin,您可以使用此功能,它是 perlin 的快速 zig zag 版本。
function zig ( xx : float ): float{ //lfo nz -1,1
xx= xx+32;
var x0 = Mathf.Floor(xx);
var x1 = x0+1;
var v0 = (Mathf.Sin (x0*.014686)*31718.927)%1;
var v1 = (Mathf.Sin (x1*.014686)*31718.927)%1;
return Mathf.Lerp( v0 , v1 , (xx)%1 )*2-1;
}
这是我为我制作的网站写的东西。它会为任何具有该类的 div 自动生成随机的平面背景颜色 .flat-color-gen
. 。仅当向页面添加 css 时才需要 Jquery;这对于主要部分来说不是必需的,即 generateFlatColorWithOrder()
方法。
(function($) {
function generateFlatColorWithOrder(num, rr, rg, rb) {
var colorBase = 256;
var red = 0;
var green = 0;
var blue = 0;
num = Math.round(num);
num = num + 1;
if (num != null) {
red = (num*rr) % 256;
green = (num*rg) % 256;
blue = (num*rb) % 256;
}
var redString = Math.round((red + colorBase) / 2).toString();
var greenString = Math.round((green + colorBase) / 2).toString();
var blueString = Math.round((blue + colorBase) / 2).toString();
return "rgb("+redString+", "+greenString+", "+blueString+")";
//return '#' + redString + greenString + blueString;
}
function generateRandomFlatColor() {
return generateFlatColorWithOrder(Math.round(Math.random()*127));
}
var rr = Math.round(Math.random()*1000);
var rg = Math.round(Math.random()*1000);
var rb = Math.round(Math.random()*1000);
console.log("random red: "+ rr);
console.log("random green: "+ rg);
console.log("random blue: "+ rb);
console.log("----------------------------------------------------");
$('.flat-color-gen').each(function(i, obj) {
console.log(generateFlatColorWithOrder(i));
$(this).css("background-color",generateFlatColorWithOrder(i, rr, rg, rb).toString());
});
})(window.jQuery);
使用 不同颜色.
用 JavaScript 编写。
它生成一个调色板 视觉上 不同的颜色。
unique-colors 是高度可配置的:
- 选择调色板中有多少种颜色
- 将色调限制在特定范围内
- 将色度(饱和度)限制在特定范围
- 将亮度限制在特定范围内
- 配置调色板的总体质量