如何生成随机恒定颜色"对于给定的字符串?

时间:2015-10-07 14:03:41

标签: c# wpf

如何生成"随机常数颜色"对于运行时给定的字符串?

因此,给定的字符串值将始终具有相同的颜色,但不同的字符串将具有不同的颜色。

就像gmail如何为发件人姓名指定颜色一样。

由于

回应评论:

  1. 考虑从哈希码生成颜色。
  2. 颜色不会被存储,而是从哈希码生成。

4 个答案:

答案 0 :(得分:3)

我不知道任何专用方法,但这是一个基于给定字符串生成MD5的十六进制值的简单方法:

ZiggeoSdk = Meteor.npmRequire('./ziggeo/ziggeo-sdk.min.js');
ZiggeoSdk.init('86381021416de9dcb1c04c74195bc5ee', '54d16056f809ee8c5f715ac7a03d8374', 'ecd3fdc60ac0318642301713d8758e1c');

示例:

  1. example@example.com

    - > 23463B

  2. info@google.com

    - > 3C9015

  3. stack@exchange.com

    - > 7CA5E8

  4. 修改

    我没有对它进行足够的测试,因此您可能需要稍微调整一下以获得更多不同且独特的值。

    <强> EDIT2:

    如果您想要透明度,请查看this问题/答案。通过将using System.Security.Cryptography; using System.Text; static string GetColor(string raw) { using (MD5 md5Hash = MD5.Create()) { byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(raw)); return BitConverter.ToString(data).Replace("-", string.Empty).Substring(0, 6); } } 设置为Substring,您应该返回带有Alpha通道的字符串。

答案 1 :(得分:1)

与其他答案的建议类似(以某种形式散列字符串,然后使用该散列来选择颜色),但不使用散列直接计算颜色,而是将其用作“可接受”数组的索引“颜色。

class ColorPicker
{
    public ColorPicker(int colorCount)
    {
        //The ".Skip(2)" makes it skip pure white and pure black.
        // If you want those two, take out the +2 and the skip.
        _colors = ColorGenerator.Generate(colorCount + 2).Skip(2).ToArray();
    }
    private readonly Color[] _colors;

    public Color StringToColor(string message)
    {
        int someHash = CalculateHashOfStringSomehow(message);
        return _colors[someHash % _colors.Length];
    }

    private int CalculateHashOfStringSomehow(string message)
    {
        //TODO: I would not use "message.GetHashCode()" as you are not
        // guaranteed the same value between runs of the program.
        // Make up your own algorithom or use a existing one that has a fixed 
        // output for a given input, like MD5.
    }
}

这样可以防止在计划显示带有白色背景和其他类似问题的文本时出现白色等问题。

要填充Color[] ColorGeneratorColorGenerator,或者只是制作自己的预定义颜色列表,这些颜色在任何背景上都会很好用。

<强>附录
如果链接断开,这里是public static class ColorGenerator { // RYB color space private static class RYB { private static readonly double[] White = { 1, 1, 1 }; private static readonly double[] Red = { 1, 0, 0 }; private static readonly double[] Yellow = { 1, 1, 0 }; private static readonly double[] Blue = { 0.163, 0.373, 0.6 }; private static readonly double[] Violet = { 0.5, 0, 0.5 }; private static readonly double[] Green = { 0, 0.66, 0.2 }; private static readonly double[] Orange = { 1, 0.5, 0 }; private static readonly double[] Black = { 0.2, 0.094, 0.0 }; public static double[] ToRgb(double r, double y, double b) { var rgb = new double[3]; for (int i = 0; i < 3; i++) { rgb[i] = White[i] * (1.0 - r) * (1.0 - b) * (1.0 - y) + Red[i] * r * (1.0 - b) * (1.0 - y) + Blue[i] * (1.0 - r) * b * (1.0 - y) + Violet[i] * r * b * (1.0 - y) + Yellow[i] * (1.0 - r) * (1.0 - b) * y + Orange[i] * r * (1.0 - b) * y + Green[i] * (1.0 - r) * b * y + Black[i] * r * b * y; } return rgb; } } private class Points : IEnumerable<double[]> { private readonly int pointsCount; private double[] picked; private int pickedCount; private readonly List<double[]> points = new List<double[]>(); public Points(int count) { pointsCount = count; } private void Generate() { points.Clear(); var numBase = (int)Math.Ceiling(Math.Pow(pointsCount, 1.0 / 3.0)); var ceil = (int)Math.Pow(numBase, 3.0); for (int i = 0; i < ceil; i++) { points.Add(new[] { Math.Floor(i/(double)(numBase*numBase))/ (numBase - 1.0), Math.Floor((i/(double)numBase) % numBase)/ (numBase - 1.0), Math.Floor((double)(i % numBase))/ (numBase - 1.0), }); } } private double Distance(double[] p1) { double distance = 0; for (int i = 0; i < 3; i++) { distance += Math.Pow(p1[i] - picked[i], 2.0); } return distance; } private double[] Pick() { if (picked == null) { picked = points[0]; points.RemoveAt(0); pickedCount = 1; return picked; } var d1 = Distance(points[0]); int i1 = 0, i2 = 0; foreach (var point in points) { var d2 = Distance(point); if (d1 < d2) { i1 = i2; d1 = d2; } i2 += 1; } var pick = points[i1]; points.RemoveAt(i1); for (int i = 0; i < 3; i++) { picked[i] = (pickedCount * picked[i] + pick[i]) / (pickedCount + 1.0); } pickedCount += 1; return pick; } public IEnumerator<double[]> GetEnumerator() { Generate(); for (int i = 0; i < pointsCount; i++) { yield return Pick(); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public static IEnumerable<Color> Generate(int numOfColors) { var points = new Points(numOfColors); foreach (var point in points) { var rgb = RYB.ToRgb(point[0], point[1], point[2]); yield return Color.FromArgb( (int)Math.Floor(255 * rgb[0]), (int)Math.Floor(255 * rgb[1]), (int)Math.Floor(255 * rgb[2])); } } }

的副本
{{1}}

答案 2 :(得分:0)

3个整数变量r,g和b。

以3为步长循环遍历字符串中的每个字符并添加字符代码。

r += n + 0
g += n + 1
b += n + 2

循环后,将r,g和b取模255并使用Color.FromARGB创建颜色。

不能保证颜色会很漂亮,有些字符串的颜色可能会非常接近。

答案 3 :(得分:0)

我看到一些非常好的回答者,但是虽然它有助于通过一点点有趣的解决方案来生成字符串的颜色,但哈希版本看起来是最好的方式,但是如果这给了任何一个灵感,那么就可以了

        ConsoleKeyInfo ch = new ConsoleKeyInfo();
        while (ch.KeyChar != 'e')
        {
            Console.WriteLine("type string to seed color");
            string s = Console.ReadLine(); // gets text from input, in this case the command line
            double d=0;
            foreach(char cha in s.ToCharArray())
            {
                d=+ (int)cha; // get the value and adds it 
            }
            d= (255/(Math.Pow(0.2,-0.002 *d))); // Generates a seed like value from i where 255 is the maximum. basicly 255/0.2^(-0.002*d)

            int i = Convert.ToInt32(d); //then convets and get rid of the decimels
            Color c = Color.FromArgb(i, i, i);// add a bit more calculation for varieng colers.
            Console.WriteLine(c.Name);
            Console.WriteLine("To Exit press e");
            ch = Console.ReadKey()
       }

Edit1:它肯定需要一些tweeking,因为字符串的颜色越长,但我认为可以通过一些工作来实现它:)