# Algorithm to randomly generate an aesthetically-pleasing color palette

308

I'm looking for a simple algorithm to generate a large number of random, aesthetically pleasing colors. So no crazy neon colors, colors reminiscent of feces, etc.

I've found solutions to this problem but they rely on alternative color palettes than RGB. I would rather just use straight RGB than mapping back and forth. These other solutions also can at most generate only 32 or so pleasing random colors.

Any ideas would be great.

This question is tagged with `algorithm` `colors`

432

You could average the RGB values of random colors with those of a constant color:

(example in 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;
}
``````

Mixing random colors with white (255, 255, 255) creates neutral pastels by increasing the lightness while keeping the hue of the original color. These randomly generated pastels usually go well together, especially in large numbers.

Here are some pastel colors generated using the above method: You could also mix the random color with a constant pastel, which results in a tinted set of neutral colors. For example, using a light blue creates colors like these: Going further, you could add heuristics to your generator that take into account complementary colors or levels of shading, but it all depends on the impression you want to achieve with your random colors.

87

I would use a color wheel and given a random position you could add the golden angle (137,5 degrees)

http://en.wikipedia.org/wiki/Golden_angle

in order to get different colours each time that do not overlap.

Adjusting the brightness for the color wheel you could get also different bright/dark color combinations.

I've found this blog post that explains really well the problem and the solution using the golden ratio.

http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/

UPDATE: I've just found this other approach:

It's called RYB(red, yellow, blue) method and it's described in this paper:

http://threekings.tk/mirror/ryb_TR.pdf

as "Paint Inspired Color Compositing".

The algorithm generates the colors and each new color is chosen to maximize its euclidian distance to the previously selected ones.

Here you can find a a good implementation in javascript:

http://afriggeri.github.com/RYB/

UPDATE 2:

The Sciences Po Medialb have just released a tool called "I want Hue" that generate color palettes for data scientists. Using different color spaces and generating the palettes by using k-means clustering or force vectors ( repulsion graphs) The results from those methods are very good, they show the theory and an implementation in their web page.

http://tools.medialab.sciences-po.fr/iwanthue/index.php

23

In 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;
}
``````

11

Converting to another palette is a far superior way to do this. There's a reason they do that: other palettes are 'perceptual' - that is, they put similar seeming colors close together, and adjusting one variable changes the color in a predictable manner. None of that is true for RGB, where there's no obvious relationship between colors that "go well together".

6

I've had success using TriadMixing and CIE94 to avoid similar colors. The following image uses input colors red, yellow, and white. See here. 5

An answer that shouldn't be overlooked, because it's simple and presents advantages, is sampling of real life photos and paintings. sample as many random pixels as you want random colors on thumbnails of modern art pics, cezanne, van gogh, monnet, photos... the advantage is that you can get colors by theme and that they are organic colors. just put 20 - 30 pics in a folder and random sample a random pic every time.

Conversion to HSV values is a widespread code algorithm for psychologically based palette. hsv is easier to randomize.

4

In 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;
}
``````

3

Use distinct-colors.

Written in javascript.

It generates a palette of visually distinct colors.

distinct-colors is highly configurable:

• Choose how many colors are in the palette
• Restrict the hue to a specific range
• Restrict the chroma (saturation) to a specific range
• Restrict the lightness to a specific range
• Configure general quality of the palette

3

Here is quick and dirty color generator in C# (using 'RYB approach' described in this article). It's a rewrite from JavaScript.

Use:

``````List<Color> ColorPalette = ColorGenerator.Generate(30).ToList();
``````

First two colors tend to be white and a shade of black. I often skip them like this (using Linq):

``````List<Color> ColorsPalette = ColorGenerator
.Generate(30)
.Skip(2) // skip white and black
.ToList();
``````

Implementation:

``````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;
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 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++)
{
{
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;
points.RemoveAt(0);
pickedCount = 1;
return picked;
}

var d1 = Distance(points);
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, point, point);
yield return Color.FromArgb(
(int)Math.Floor(255 * rgb),
(int)Math.Floor(255 * rgb),
(int)Math.Floor(255 * rgb));
}
}
}
``````

3

David Crow's method in an R two-liner:

``````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))
}
``````

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;
}
``````

For pastel, pass in higher luma dark/light integers - ie fnGetRandomColour(120, 250)

Credits: all credits to http://paulirish.com/2009/random-hex-color-code-snippets/ stackoverflow.com/questions/12043187/how-to-check-if-hex-color-is-too-black

1

## JavaScript adaptation of David Crow's original answer, IE and Nodejs specific code included.

``````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))) * 256));
green = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))) * 256));
blue = Math.floor((('0.' + window.crypto.getRandomValues(new Uint32Array(1))) * 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) + ')';
}
``````

Run the function using:

``````generateRandomComplementaryColor(240, 240, 240);
``````

0

I'd strongly recommend using a CG HSVtoRGB shader function, they are awesome... it gives you natural color control like a painter instead of control like a crt monitor, which you arent presumably!

This is a way to make 1 float value. i.e. Grey, into 1000 ds of combinations of color and brightness and saturation etc:

``````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);
``````

result is AWESOME COLOR RANDOMIZATION! it's not natural but it uses natural color gradients and it looks organic and controlleably irridescent / pastel parameters.

For perlin, you can use this function, it is a fast zig zag version of perlin.

``````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;
}
``````

0

Here is something I wrote for a site I made. It will auto-generate a random flat background-color for any div with the class `.flat-color-gen`. Jquery is only required for the purposes of adding css to the page; it's not required for the main part of this, which is the `generateFlatColorWithOrder()` method.

``````(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);
``````

0

you could have them be within a certain brightness. that would control the ammount of "neon" colors a bit. for instance, if the "brightness"

``````brightness = sqrt(R^2+G^2+B^2)
``````

was within a certain high bound, it would have a washed out, light color to it. Conversely, if it was within a certain low bound, it would be darker. This would eliminate any crazy, standout colors and if you chose a bound really high or really low, they would all be fairly close to either white or black.