Is there a best practice on how to hash an arbitrary string into a RGB color value? Or to be more general: to 3 bytes.
You're asking: When will I ever need this? It doesn't matter to me, but imagine those tube graphs on any GitHub network page. There you can see something like this:
Where every colored line means a distinct git branch. The low tech approach to color these branches would be a CLUT (color lookup table). The more sophisticated version would be:
$branchColor = hashStringToColor(concat($username,$branchname));
Because you want a static color every time you see the branches representation. And for bonus points: How do you ensure an even color distribution of that hash function?
So the answer to my question boils down to the implementation of hashStringToColor()
.
White: RGB(255,255,255) Red: RGB(255,0,0) Green: RGB(0,255,0)
In RGB, a color is defined as a mixture of pure red, green, and blue lights of various strengths. Each of the red, green and blue light levels is encoded as a number in the range 0.. 255, with 0 meaning zero light and 255 meaning maximum light.
A good hash function will provide a near uniform distribution over the key space. This reduces the question to how do I convert a random 32 bit number to a 3 byte RGB space. I see nothing wrong with just taking the low 3 bytes.
int hash = string.getHashCode(); int r = (hash & 0xFF0000) >> 16; int g = (hash & 0x00FF00) >> 8; int b = hash & 0x0000FF;
For any Javascript users out there, I combined the accepted answer from @jeff-foster with the djb2
hash function from erlycoder.
The result per the question:
function djb2(str){ var hash = 5381; for (var i = 0; i < str.length; i++) { hash = ((hash << 5) + hash) + str.charCodeAt(i); /* hash * 33 + c */ } return hash; } function hashStringToColor(str) { var hash = djb2(str); var r = (hash & 0xFF0000) >> 16; var g = (hash & 0x00FF00) >> 8; var b = hash & 0x0000FF; return "#" + ("0" + r.toString(16)).substr(-2) + ("0" + g.toString(16)).substr(-2) + ("0" + b.toString(16)).substr(-2); }
UPDATE: Fixed the return string to always return a #000000 format hex string based on an edit by @alexc (thanks!).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With