8

Heading

Is there a way to map an arbitrary string to a HEX COLOR code. I tried to compute the HEX number for string using string hashcode. Now I need to convert this hex number to six digits which are in HEX color code range. Any suggestions ?

String [] programs = {"XYZ", "TEST1", "TEST2", "TEST3", "SDFSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"};

for(int i = 0; i < programs.length; i++) {
  System.out.println( programs[i] + " -- " + Integer.toHexString(programs[i].hashCode()));
}
2
  • 2
    Isn't any six digit hex code a valid RGB color? Commented Mar 17, 2010 at 18:18
  • I think that is true, range for each RGB color component is 0-256. Any 2 HEX digits together will produce numbers up to 256.
    – tech20nn
    Commented Mar 24, 2010 at 17:23

5 Answers 5

15

If you don't really care about the "meaning" of the color you can just split up the bits of the int (remove the first for just RGB instead of ARGB)

String [] programs = {"XYZ", "TEST1", "TEST2", "TEST3", "SDFSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"};

for(int i = 0; i < programs.length; i++) {
  System.out.println( programs[i] + " -- " + intToARGB(programs[i].hashCode()));
}
....
public static String intToARGB(int i){
    return Integer.toHexString(((i>>24)&0xFF))+
        Integer.toHexString(((i>>16)&0xFF))+
        Integer.toHexString(((i>>8)&0xFF))+
        Integer.toHexString((i&0xFF));
}
1
  • Here's the same for C# private string StringToARGB(string text) { int i = text.GetHashCode(); return "#" + (((i >> 24) & 0xFF)).ToString("X2") + (((i >> 16) & 0xFF)).ToString("X2") + (((i >> 8) & 0xFF)).ToString("X2") + ((i & 0xFF)).ToString("X2"); } And you can create a Color object like so: Color color = (Color)(new ColorConverter()).ConvertFromString(this.StringToARGB(source));
    – Sal
    Commented Mar 26, 2019 at 16:33
5

How about anding the hashcode with 0x00FFFFFF (or 0xFFFFFF if you want to default the alpha channel)? For example:

private String getColorCode(String inputString)
{
    String colorCode = String.format("#%06x", 0xFFFFFF & inputString.hashCode());
}
0
3

I ran into this question while looking for a Ruby solution, so I thought I would add an answer for Ruby in case someone follows the same path I did. I ended up using the following method, which creates the same six digit hex code from a string by using String.hash and the optional base-specifying parameter of Fixnum.to_s. It slices from 1 rather than 0 to skip negative signs.

def color_from_string(query)
  '#'+query.hash.to_s(16).slice(1,6)
end
2

The following class takes a String and converts it to a color. It is a simplified Java port of the Color-Hash TypeScript project (MIT license): https://github.com/zenozeng/color-hash. The original project contains some parameters to adjust the generated colours. These were not included.

The advantage of the Color-Hash algorithm, compared using a hash value directly, is that the generated colours are more perceptually uniform.

A lot of copy/paste was going on here:

Result:

XYZ: #bf40b3
TEST1: #86432d
TEST2: #3a2dd2
TEST3: #bf4073
SDFSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS: #53ac8b
public class ColorHash
{

  private static final double[] LigthnessArray  = new double[] { 0.35, 0.5, 0.65 };
  private static final double[] SaturationArray = new double[] { 0.35, 0.5, 0.65 };

  public Color generateColor(String input) throws NoSuchAlgorithmException
  {
    // Easiest way would be String.hashCode()
    // But "Test1" and "Test2" result in practically the same color
    // Therefore another hash algorithm should be used
    MessageDigest md = MessageDigest.getInstance("MD5");
    md.update(input.getBytes());
    byte[] digest = md.digest();
    int hash = Math.abs(ByteBuffer.wrap(digest).getInt());

    double hue, saturation, lightness;

    hue = hash % 359 / 359.; // note that 359 is a prime
    hash = (int) Math.ceil(hash / 360);
    saturation = SaturationArray[hash % SaturationArray.length];
    hash = (int) Math.ceil(hash / SaturationArray.length);
    lightness = LigthnessArray[hash % LigthnessArray.length];

    return hslColor((float) hue, (float) saturation, (float) lightness);
  }

  public String generateColorHash(String input) throws NoSuchAlgorithmException
  {
    return "#" + Integer.toHexString(generateColor(input).getRGB()).substring(2);
  }

  private static Color hslColor(float h, float s, float l)
  {
    float q, p, r, g, b;

    if (s == 0)
    {
      r = g = b = l; // achromatic
    } else
    {
      q = l < 0.5 ? (l * (1 + s)) : (l + s - l * s);
      p = 2 * l - q;
      r = hue2rgb(p, q, h + 1.0f / 3);
      g = hue2rgb(p, q, h);
      b = hue2rgb(p, q, h - 1.0f / 3);
    }
    return new Color(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
  }

  private static float hue2rgb(float p, float q, float h)
  {
    if (h < 0)
    {
      h += 1;
    }

    if (h > 1)
    {
      h -= 1;
    }

    if (6 * h < 1) { return p + ((q - p) * 6 * h); }
    if (2 * h < 1) { return q; }
    if (3 * h < 2) { return p + ((q - p) * 6 * ((2.0f / 3.0f) - h)); }

    return p;
  }
  
  public static void main(String[] args) throws NoSuchAlgorithmException
  {
    String [] programs = {"XYZ", "TEST1", "TEST2", "TEST3", "SDFSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"};
    ColorHash gen = new ColorHash();
    for(String p : programs) {
      System.out.println(p + ": " + gen.generateColorHash(p));
    }
  }

}
1

In case anyone else is looking for a solution for Flutter/Dart:

    Color _fromInt(int i) {
      final a = (i >> 24) & 0xFF;
      final r = (i >> 16) & 0xFF;
      final g = (i >> 8) & 0xFF;
      final b = i & 0xFF;
      return Color.fromARGB(a, r, g, b);
    }

It's also worth noting that with certain background colours e.g. black, it may be difficult to differentiate the colours.

To this end, I set the alpha channel to the max value of 255:

    Color _fromInt(int i) {
      const a = 255;
      final r = (i >> 16) & 0xFF;
      final g = (i >> 8) & 0xFF;
      final b = i & 0xFF;
      return Color.fromARGB(a, r, g, b);
    }

Not the answer you're looking for? Browse other questions tagged or ask your own question.