Chaîne de hachage en couleur RVB
Existe-t-il une meilleure pratique pour hacher une chaîne arbitraire dans une valeur de couleur RVB? Ou pour être plus général: à 3 octets.
Vous demandez: Quand aurai-je besoin de ça? Cela n'a pas d'importance pour moi, mais imaginez ces graphiques de tubes sur N'importe quelle page Réseau GitHub . Là, vous pouvez voir quelque chose comme ceci:
Où chaque ligne colorée signifie une branche git distincte. L'approche low tech pour colorer ces branches serait un CLUT (table de recherche de couleur). Le plus version sophistiquée serait:
$branchColor = hashStringToColor(concat($username,$branchname));
Parce que vous voulez une couleur statique chaque fois que vous voyez la représentation des branches. Et pour les points bonus: Comment assurez-vous une distribution uniforme des couleurs de cette fonction de hachage?
Donc la réponse à ma question se résume à la mise en œuvre de hashStringToColor()
.
5 réponses
Une bonne fonction de hachage fournira une distribution quasi uniforme sur l'espace clé. Cela réduit la question de savoir comment convertir un nombre 32 bits aléatoire en un espace RVB de 3 octets. Je ne vois rien de mal à simplement prendre les 3 octets bas.
int hash = string.getHashCode();
int r = (hash & 0xFF0000) >> 16;
int g = (hash & 0x00FF00) >> 8;
int b = hash & 0x0000FF;
Pour tous les utilisateurs Javascript, j'ai combiné la réponse acceptée de @ jeff-foster avec la fonction de hachage djb2
deerlycoder .
Le résultat par la 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 : Correction de la chaîne de retour pour toujours renvoyer une chaîne hexadécimale au format #000000 basée sur une édition par @alexc (merci!).
J'ai essayé toutes les solutions fournies par d'autres mais j'ai constaté que des chaînes similaires (string1 vs string2) produisaient des couleurs trop similaires à mon goût. Par conséquent, j'ai construit mon propre influencé par l'entrée et les idées des autres.
Celui-ci calculera la somme de contrôle MD5 de la chaîne, et prendra les 6 premiers chiffres hexadécimaux pour définir le code RVB 24 bits.
La fonctionnalité MD5 est un plug-in jQuery open-source. La fonction JS va comme suit:
function getRGB(str){
var hash = $.md5(str);
var rgb = '#' + hash.substring(0,2) + hash.substring(2,4) + hash.substring(4,6);
return rgb;
}
Un lien vers ce travail l'exemple est sur jsFiddle . Il suffit d'entrer une chaîne dans le champ de saisie et appuyez sur Entrée, et le faire encore et encore pour comparer vos résultats.
Je viens de construire une bibliothèque JavaScript nommée color-hash, qui peut générer de la couleur en fonction de la chaîne donnée(en utilisant l'espace colorimétrique HSL et BKDRHash).
Repo: https://github.com/zenozeng/color-hash
Démo: https://zenozeng.github.io/color-hash/demo/
Par exemple, Voici comment Java calcule le hashcode d'une chaîne (ligne 1494 et suivantes). Il renvoie un int
. Vous pouvez ensuite calculer le modulo de ce int
avec 16 777 216 (2^24 = 3 octets) pour obtenir un nombre" compatible RGB".
C'est un calcul déterministe donc le même mot(s) aura toujours la même couleur. La probabilité de collision de hachage (2 chaînes ayant la même couleur) est faible. Pas sûr de la distribution des couleurs, mais probablement assez aléatoire.