3

I have various objects in my database identified by unique System.Guid's. When I display them, I would like each of them to have a unique color based on their guid.

So I want something like this:

public Color ColorFromGuid(Guid guid) { /* ?? */ }

Where

ColorFromGuid(databaseObject1.Guid) == ColorFromGuid(databaseObject1.Guid)
ColorFromGuid(databaseObject2.Guid) == ColorFromGuid(databaseObject2.Guid)
ColorFromGuid(databaseObject1.Guid) != ColorFromGuid(databaseObject2.Guid)

What would be the best way to do this?

EDIT Obviously there are WAY more unique guids than colors, so there's no way that every guid will have it's own unique color. I'm just looking for a good variety.

Entity
  • 7,972
  • 21
  • 79
  • 122
  • 1
    I think Guid is 36 charachter. first 12 char for Red,second 12 char for Green and 3rd 12 char for Blue. convert these 12 chars to int. and produce random number 0-255 by this value. – Habib Zare Aug 11 '12 at 02:55
  • @LarsTech There would potentially be trillions and trillions of entries in said array. That seems a little inefficient... – Entity Aug 11 '12 at 02:55

5 Answers5

5

You could do:

return Color.FromArgb(guid.GetHashCode());

If you need an opaque color, use the overload of Color.FromArgb that lets you specify the alpha. If you want similar GUIDs to generate very different colors, you can do a different sort of hash on the Guid, e.g. an MD5 hash, and get the number to generate your color from that.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
3

How about something like this:

public Color ColorFromGuid(Guid guid)
{
    var values = guid.ToByteArray().Select(b => (int)b);
    int red = values.Take(5).Sum() % 255;
    int green = values.Skip(5).Take(5).Sum() % 255;
    int blue = values.Skip(10).Take(5).Sum() % 255;

    Color color = Color.FromArgb(red, green, blue);
    return color;
}

This may not be ideal, but you get a color for every GUID, and the same GUID should result in the same color each time.

  • instead of `.Select(b => (int)b)`, couldn't you use `.Cast()`? – Adam Aug 11 '12 at 03:24
  • @codesparkle: That earns an `InvalidCastException` in LINQPad. I didn't bother to run Visual Studio. –  Aug 11 '12 at 03:27
  • indeed, same result in VS, because `Cast` [boxes the items in the input sequence](http://stackoverflow.com/a/445497/1106367). – Adam Aug 11 '12 at 03:46
1

If you do this with a function you'll be disappointed.

There are many times more Guids than colours, and thus many Guids will map to the same colour. Many times more Guids will map to colours that are too close to differentiate (e.g. #FFFF9999 and #FFFF9998). In reality, you can only tell the difference between a handful of colours - say 50 at an absolute maximum.

Guids are not random. Just repeat that to yourself: Guids are not random. Especially if you are using database generated Guids, which may be what are known as 'sequential uniqueidentifiers', where the first half of the Guid is the same. Does that mean you'll just end up with different shades of pink for each of your Guids? Perhaps.

So unless you know the distribution of your Guids and are able to create a function that maps that distribution to a suitable colour distribution, you won't be happy with the colours generated by a function.

The simplest way to do this in a extentible way is to create a simple table in your database containing two columns - a colour (names, hex codes or RGB values) and a Guid. The most time consuming part of doing that will be choosing the colours. This allows you to change the colour of a particular item if it's too similar to another colour. No tricks, just simple mapping.

Kirk Broadhurst
  • 27,836
  • 16
  • 104
  • 169
1

If you need color for HTML you may use this, or similar:

cssColorcode =  "#" + myguid.Substring(0, 6); 
// result can be something like: #ab3fa4

Guid is kind of a hexa, and Html css color codes can be represented in a similar format.

Maybe not perfect, but most simple.

Estevez
  • 1,014
  • 8
  • 13
0

I use something like the following in a few of my applications.

Color = Color.ParseColor("#" + (Guid.NewGuid().ToString()).Substring(0, 6));

Taking the first 6 characters from the GUID and parsing it as a HEX color code.

Moir
  • 379
  • 4
  • 14