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 doe
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!).
As an example, this is how Java calculates the hashcode of a string (line 1494 and following). It returns an int
. You can then calculate the modulo of that int
with 16,777,216 (2^24 = 3 bytes) to get an "RGB-compatible" number.
It is a deterministic calculation so the same word(s) will always have the same colour. The likelihood of hash collision (2 strings having the same colour) is small. Not sure about the colour distribution, but probably fairly random.
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;
I tried all the solutions others provided but found that similar strings (string1 vs string2) produce colors that are too similar for my liking. Therefore, I built my own influenced by the input and ideas of others.
This one will compute the MD5 checksum of the string, and take the first 6 hex digits to define the RGB 24-bit code.
The MD5 functionality is an open-source JQuery plug in. The JS function goes as follows:
function getRGB(str) {
return '#' + $.md5(str).substring(0, 6);
}
A link to this working example is on jsFiddle. Just input a string into the input field and press enter, and do so over and over again to compare your findings.
I just build a JavaScript library named color-hash, which can generate color based on the given string (using HSL color space and BKDRHash).
Repo: https://github.com/zenozeng/color-hash
Demo: https://zenozeng.github.io/color-hash/demo/