How do I create a random hex string that represents a color?

Viewed 46845

I'm generating some charts that need a hex string for the colors.

Example:

<dataseries name="ford" color="FF00FF" />

I'm creating these dynamically, so I would like to generate the hex code for each dataseries randomly.

What is the best way to do this?

6 Answers

Easiest way is to use String.Format and use the hexadecimal format for the argument.

var random = new Random();
var color = String.Format("#{0:X6}", random.Next(0x1000000)); // = "#A197B9"

Samuel's answer is the best way to do this, just make sure that if you're generating the colors inside a loop that you don't instantiate a new Random object each time because new Random() seeds the generator using the system clock. Your loop is going to run faster than the clock can tick, so you'll end up generating several of the same colors over and over because random is being seeded with the same value.

It should look something like this:

int numColors = 10;
var colors = new List<string>();
var random = new Random(); // Make sure this is out of the loop!
for (int i = 0; i < numColors; i++) 
{
    colors.Add(String.Format("#{0:X6}", random.Next(0x1000000)));
}

instead of:

int numColors = 10;
var colors = new List<string>();
for (int i = 0; i < numColors; i++) 
{
    var random = new Random(); // Don't put this here!
    colors.Add(String.Format("#{0:X6}", random.Next(0x1000000)));
}

IMO, purely random colours may not be preferable as you need colours that are distinguishable in human eyes.

What about presetting a number of colours and picking them randomly?

Perhaps you could find better answers in some open source charting libraries.

A good way of generating a nice set of colours is to define them using fixed saturation and brightness and vary the hue.

  1. Set saturation and brightness to something you like, say 50% saturation and 90% brightness.
  2. Now divide the 360 degrees of hue by the number of distinct colours you want.
  3. Pick colours from HSV using that interval for hue, and the fixed S and V.

This gives you a nice set of colours, which all look like they came from the same 'set' -- all pastel, or all intense, or all off-white, whatever. And it's pretty easy to code if you've got Color.FromHSV().

It probably stops working once you get too many colours though, they'll be indistinguishable. But you'll probably get that problem anyway.

In pseudo code:

Sat = 0.5 * 255 //assuming we want range 0-255...
Brightness = 0.9 * 255
NumberOfColours = 7
HueSeparation = 360 / 7
Colors = []
for (i = 0 ; i< NumberOfColours; i++)
     Colors.Add(Color.FromHSV(HueSeparation * i, Sat, Brightness)

or

n = 7
Colors = [Color.FromHSV(x*360/n, 128, 230) for x in range(n)]

(I do like list comprehensions...)

Random rand = new Random(); // specify a seed
int r = rand.Next(0x1000000); 
Console.WriteLine("#{0:X6}", r);

I noticed that you (Rahkim) commented on Greg's post that you wish you could put his idea (keeping the saturation and value constant, and just varying the hue...a good idea) into code. You can! Or, rather, someone already has for you!

I found this blog post on Converting HSV to RGB colour using C#, and I'm sure there are more out there. You'll probably end up with a nicer suite of colors this way than by picking them totally randomly.

Additionally, of course, this method makes it simple to get a nice set of colors...since the Hue goes from 0-359, you could do something like set your Hue something like this:

Hue = (PreviousHue + 50) % 360;

(I picked 50 since it doesn't go into 360 evenly, so if you go beyond 360 you won't start repeating hues instantly. You'd have to toy around with the value to get an ideal separation depending on how many different colors you're expecting.)

This way you don't have to worry about the case where the code is randomly picking two colors that are super close to one another when there is still lots of unused "hue" space.

Related