18

I want to draw some data into a texture: many items in a row. They aren't created in order, and they may all be different sizes (think of a memory heap). Each data item is a small rectangle and I want to be able to distinguish them apart, so I'd like each of them to have a unique colour.

Now I could just use rand() to generate RGB values and hope they are all different, but I suspect I won't get good distribution in RGB space. Is there a better way than this? E.g. what is a good way of cycling through different colours before they (nearly) repeat?

The colours don't have to match with any data in the items. I just want to be able to look at many values and see that they are different, as they are adjacent.

I could figure something out but I think this is an interesting question. :)

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
Nick
  • 27,566
  • 12
  • 60
  • 72

6 Answers6

13

Using the RGB color model is not a good way to get a good color mix. It's better to use another color model to generate your color, and then convert from that color model to RGB.

I suggest you the HSV or HSL color model instead, in particular you want to vary the Hue.

If you want X different color values, vary them from 0 to 360 with a step size of 360 divided by X.

Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 1
    0, 360 (same colors), 180, 300, 390, 102, 162, 213, 258, 298 (basically 300 again), 334, 367, (basically 360 a third time). – Tatarize Nov 30 '13 at 07:35
4

Whats your sample space... how many items are we talking.

You could build up an array of RGB Triples from

for(int r = 0; r < 255; r = r+16)
   for(int g = 0; g < 255; g = g+16)
      for(int b = 0; b < 255; b = b+16)
           // take r, g, b and add it to a list

Then randomise your list and iterate through it. that'd give you 16^3 (4096) different colors before a repeated color.

Eoin Campbell
  • 43,500
  • 17
  • 101
  • 157
  • That is identical to rand(0,16) << 20 | rand(0,16) << 12 | rand(0,16) << 4. It's a random color between #000 and #FFF in 12 bit color, checking for repeats. Your #0A0 and #090 for example especially with the color distinctions with greens are going to look pretty identical. – Tatarize Nov 30 '13 at 07:53
4

In general RGB isn't a great color space for doing these sorts of things because it's perceptually nonlinear, for starters. This means that equal distances moved between RGB triplets do not look equally different to our eyes.

I'd probably work in the L*c*h* space (see also) space, or HSL space, and just generate a uniform spacing in hue. These spaces have been designed to be approximately perceptually linear.

simon
  • 7,044
  • 2
  • 28
  • 30
  • 2
    Even in HSL regular spacing of `hue` is [not perceptually linear](http://phrogz.net/tmp/colordifferences). – Phrogz Feb 22 '12 at 23:53
  • 1
    HSL is a direct math conversion from RGB irrespective of the particular hue. The spaces are not designed to be linear. LCH is a modification of LAB which actually does requires hue based streatching to better fit with the human eye. – Tatarize Nov 30 '13 at 07:40
2

Google "delta e cie 2000"; the colour-difference formula is useful for determining apparent (visual) distance between 2 colours. (On a monitor; there's a different formula for pigments.) It operates on colours in Lab space (props to simon), but applies a perceptual calculation of difference.

We found that a number around 1.5 was sufficient to ensure visually distinct colours (i.e. you can tell the difference if they are near one another), but if you want identifiable colours (you can find any colour in a legend) you'll need to bump that up.

As to creating a set of colours... I'd probably start at some corner of Lab space, and walk around it using a step size that gives large enough visual differences (note: it's not linear, so step size will probably have to be adaptive) and then randomize the list.

user280592
  • 41
  • 1
0

This is very similar to the four-colour problem relating to colouring maps, this might yield some interesting solutions for you:

Four colour theorem

Lazarus
  • 41,906
  • 4
  • 43
  • 54
  • 2
    It really isn't at all that similar to the 4 colour problem. Nick is using as many colors as needed, whereas the coloring problems are trying to minimize how many you need.... – simon Apr 21 '09 at 15:55
  • Actually it has nothing to do with the 4 color problem, in where only 4 colors are needed and they are only used as "tags". Here he is concerned with the optical qualities (sameness) of the selected colors. – Hejazzman Apr 21 '09 at 15:57
  • 1
    I disagree, I think there is merit in the 4 colour problem here. The problem is distinguishing items arranged in a 2D plane through the use of colour. The 4 colour problem proves that you *can* solve the problem using just 4 contrasting colours. – Mark Pim Apr 21 '09 at 16:25
  • Nick's problem revolves around having a palette of colours sufficient to represent the elements he is displaying without having close contrast colours adjacent to one another. I wasn't proposing that he limit himself to 4 colours just that the theory around representing 'tiles' and how many colours are need to ensure clear contrast was relevant and could lead to some interesting solutions. Each to their own. – Lazarus Apr 21 '09 at 19:15
  • I did think about the 4 colour problem, but I don't create the rectangles in a known order. I suppose I could reassign colours and just alternate them as they are in a line: 2 colour problem! But I think reassigning colours is confusing to the user. It makes you think the existing data has changed, when it hasn't. – Nick Apr 22 '09 at 10:30
  • So is this a representation of a heap-like structure, just 1 dimensional... a line? I think I see where you are coming from on that basis and Simon/foljs are probably correct as I was thinking that this was a 2d problem. I guess on that basis the question is what is the relationship between the blocks, what's it representing? If there are instances of a fixed set of structures on this 'heap' then a colour for each and a grey (perhaps) border to allow separation. Effectively... "Tell us more!" :) – Lazarus Apr 22 '09 at 12:21
  • Yes it is 1d, and it is to visualise a heap. I may, however, draw the heap in 2d, "folding into rows" so you can see more detail. It's useful to view the data in different ways as every way gives you a different perspective. – Nick Apr 23 '09 at 09:23
  • 1
    Lazarus; the point above I was trying to make was that the 4-color problem is hard because you have to reuse colors. Nick probably has effectively as many as he wants, just needs a way to generate distiguishable colors. Very different problem (not completely unrelated, but very different). – simon Apr 23 '09 at 18:26
  • Simon, yes, agree completely. – Lazarus Apr 23 '09 at 19:11
0

If you just need a set of perceptually-distinct colors (and not an algorithm to generate them) I have created a free tool on my website that does just that:
http://phrogz.net/css/distinct-colors.html

Instead of just using even spacing in RGB or HSV space (which are not uniformly distributed with respect to human perception) the tool allows you to generate a grid of values in HSV space and it then uses the CMC(I:c) standard for color distance to throw out colors that are perceptually too close to each other. (The 'threshold' slider on the second tab allows you to control how visually distinct the colors must be, showing you the results in realtime.)

In the end, you can sort your list of generated colors by various criteria, and then evenly 'shuffle' that list so that you are guaranteed to have visually-distinct values adjacent to each other in the list. (I recommend an 'Interleave' value of about 5.)

As of this writing the tool works well with Chrome, Safari, and (via a shim) Firefox; IE9 does not support HTML5 range input sliders, which the UI uses extensively for interactive exploration.

Phrogz
  • 296,393
  • 112
  • 651
  • 745