将字符串哈希为 RGB 颜色

问题描述 投票:0回答:7

是否有关于如何将任意字符串哈希为 RGB 颜色值的最佳实践?或者更一般地说:3 个字节。

您在问:我什么时候需要这个?这对我来说并不重要,但想象一下任何 GitHub 网络页面上的那些管图。在那里你可以看到这样的东西:

git branches

每条彩色线都代表一个不同的 git 分支。为这些分支着色的低技术方法是 CLUT(颜色查找表)。更复杂的版本是:

$branchColor = hashStringToColor(concat($username,$branchname));

因为每次看到分支表示时您都需要静态颜色。还有加分点:如何确保哈希函数的颜色分布均匀?

所以我的问题的答案归结为

hashStringToColor()
的实施。

hash colors language-agnostic
7个回答
42
投票

一个好的哈希函数将在密钥空间上提供近乎均匀的分布。这将问题简化为如何将随机 32 位数字转换为 3 字节 RGB 空间。我认为只取低 3 个字节没有什么问题。

int hash = string.getHashCode();
int r = (hash & 0xFF0000) >> 16;
int g = (hash & 0x00FF00) >> 8;
int b = hash & 0x0000FF;

28
投票

对于任何 Javascript 用户,我将 @jeff-foster 接受的答案与

djb2
哈希函数从 erlycoder 结合起来。

每个问题的结果:

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);
}

更新:修复了返回字符串,使其始终基于@alexc 的编辑返回 #000000 格式的十六进制字符串(谢谢!)。


16
投票

我刚刚构建了一个名为 color-hash 的 JavaScript 库,它可以根据给定的字符串生成颜色(使用 HSL 颜色空间和 BKDRHash)。

回购:https://github.com/zenozeng/color-hash
演示:https://zenozeng.github.io/color-hash/demo/


10
投票

我尝试了其他人提供的所有解决方案,但发现相似的字符串(string1 与 string2)产生的颜色对于我的喜好来说太相似了。因此,我受到他人的意见和想法的影响而建立了自己的。

这个将计算字符串的 MD5 校验和,并采用前 6 个十六进制数字来定义 RGB 24 位代码。

MD5 功能是一个开源 JQuery 插件。 JS函数如下:

function getRGB(str) {
    return '#' + $.md5(str).substring(0, 6);
}

此工作示例的链接位于 jsFiddle。只需在输入字段中输入一个字符串并按 Enter 键,然后一遍又一遍地执行此操作以比较您的发现。


2
投票

哈希码返回一个

int
,该值是使用 javadoc 中定义的公式计算得出的。然后,您可以计算该
int
与 16,777,216(2^24 = 3 字节)的模以获得“RGB 兼容”数字。

这是一种确定性计算,因此相同的单词将始终具有相同的颜色。哈希冲突(2 个字符串具有相同颜色)的可能性很小。不确定颜色分布,但可能相当随机。


1
投票

有趣的是,像 sha256 或 md5 这样的哈希函数的常见表示形式是十六进制字符串。这是一个小提琴,它使用 10 个 6 字节段来创建 sha256 哈希值的彩色表示。它使用最后 4 个字节段来确定颜色的角度。

https://jsfiddle.net/ypx4mtnr/4/

async function sha256(message) ... see fiddle ...

   async function sha256(message) {
    // encode as UTF-8
    const msgBuffer = new TextEncoder().encode(message);                    

    // hash the message
    const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);

    // convert ArrayBuffer to Array
    const hashArray = Array.from(new Uint8Array(hashBuffer));

    // convert bytes to hex string                  
    const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
    return hashHex;
   }  
   function sha256tohtml(x,b){
var y=chunkSubstr(x,6);
return '<div style="'+
    'display: inline-block;'+
    'margin:2em;'+
    'width:128px;'+
    'height:128px;'+
    'border-radius: 512px;'+
    'background: conic-gradient('+
    '   from '+((360/65536)*parseInt(y[10],16))+'deg at 50% 50%,'+
    '   #'+y[0]+' '+(0+b)+'%,'+
    '   #'+y[0]+' 10%,'+
    '   #'+y[1]+' '+(10+b)+'%,'+
    '   #'+y[1]+' 20%,'+
    '   #'+y[2]+' '+(20+b)+'%,'+
    '   #'+y[2]+' 30%,'+
    '   #'+y[3]+' '+(30+b)+'%,'+
    '   #'+y[3]+' 40%,'+
    '   #'+y[4]+' '+(40+b)+'%,'+
    '   #'+y[4]+' 50%,'+
    '   #'+y[5]+' '+(50+b)+'%,'+
    '   #'+y[5]+' 60%,'+
    '   #'+y[6]+' '+(60+b)+'%,'+
    '   #'+y[6]+' 70%,'+
    '   #'+y[7]+' '+(70+b)+'%,'+
    '   #'+y[7]+' 80%,'+
    '   #'+y[8]+' '+(80+b)+'%,'+
    '   #'+y[8]+' 90%,'+
    '   #'+y[9]+' '+(90+b)+'%,'+
    '   #'+y[9]+' 100%);"></div>';
  }
   function chunkSubstr(str, size) {
  const numChunks = Math.ceil(str.length / size)
  const chunks = new Array(numChunks)

  for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
    chunks[i] = str.substr(o, size)
  }

  return chunks
}
   function draw(x){
    sha256(x).then((x)=>{
        var html=sha256tohtml(x,0);
            document.getElementById('addhere').innerHTML=html;
        });
   }
   window.onload=function(){
    document.getElementById('sha256string').oninput=function(){draw(this.value);}
        draw(document.getElementById('sha256string').value)
}
<html>
<input id="sha256string" value="Hello World">
 <div id="addhere"></div>
</html>


1
投票

如果您使用 C# 并想要 HSL 颜色

这是我根据Zeno Zeng编写的library编写的一个类,并在这个answer中提到。

HSLColor 类是由 Rich Newman 编写的,它在这里定义


    public class ColorHash
    {        
        
        // you can pass in a string hashing function of you choice
        public ColorHash(Func<string, int> hashFunction)
        {
            this.hashFunction = hashFunction;
        }

        // or use the default string.GetHashCode()
        public ColorHash()
        {
            this.hashFunction = (string s) => { return s.GetHashCode(); };
        }
        
        Func<string, int> hashFunction = null;

        static float[] defaultValues = new float[] { 0.35F, 0.5F, 0.65F };

        // HSLColor class is defined at https://richnewman.wordpress.com/about/code-listings-and-diagrams/hslcolor-class/
        public HSLColor HSL(string s) {
            return HSL(s, defaultValues, defaultValues);
        }

        // HSL function ported from https://github.com/zenozeng/color-hash/       
        public HSLColor HSL(string s, float[] saturationValues, float[] lightnessValues)
        {
            
            double hue;
            double saturation;
            double luminosity;

            int hash = Math.Abs(this.hashFunction(s));

            hue = hash % 359;

            hash = (int)Math.Ceiling((double)hash / 360);
            saturation = saturationValues[hash % saturationValues.Length];

            hash = (int)Math.Ceiling((double)hash / saturationValues.Length);
            luminosity = lightnessValues[hash % lightnessValues.Length];

            return new HSLColor(hue, saturation, luminosity);
        }
        
    }

© www.soinside.com 2019 - 2024. All rights reserved.