Hash string into RGB color

╄→гoц情女王★ 提交于 2019-12-20 08:24:33

问题


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().


回答1:


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;



回答2:


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!).




回答3:


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.




回答4:


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/




回答5:


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.



来源:https://stackoverflow.com/questions/11120840/hash-string-into-rgb-color

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!