0

I would like to create predictable/deterministic colours based on a string. As in, supplying two strings of the same value will generate the same colour. Here is my current code:

mt_srand(bin2hex($file)); //Convert filename to hex and seed Mersenne Twister with it
echo str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT);

However, this does not appear to work. Any idea how I can achieve this?

1 Answers1

0

Well, really depends on what parameters you want to set for forming this hex code. There are many ways you could accomplish this.

To give a simple take on it, I've made the following:

$str_u = unpack("C*", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.");

    $byte_output = [0x00, 0x00, 0x00];

    $c = 0;
    foreach($str_u as $b)
    {
        $byte_output[$c % count($byte_output)] ^= $b; 
        $c++;
    }

    var_dump($byte_output);

Basically going through every byte in the string and performing a XOR to each value in the $byte_output array, but each byte in the string only interacts with one byte in the output.

This will you give consistently the same results for different strings. It is just a simple parameter to take into account every character in the string and crunch it into a given number of bytes. That said, you could use just about any parameter you want, as long as you don't involve random functions in it.

Delta
  • 4,308
  • 2
  • 29
  • 37
  • Thank you for your answer. I tried this soloution and implemented it into my code, using `dechex()` to turn the integer bytes into hex strings. However the colours all seemed to follow an obvious pattern and didn't really seem random enough :/ I ended up going with what @Sammitch suggested which was to hash the string and truncate it to six characters, which worked really well :D – Guinea Pig Apr 15 '20 at 07:56
  • @GuineaPig Yeah, honestly that sounds like the better option. But just to throw it out there, in case you're only using English alphabet characters on your string, that can contribute to a lower amount of colors on the code I wrote (English characters always stay below 127). Adding in something to go from 127-255 might help. Like `...^= (($b < 127) && ($c % 2)) ? $b << 1 : $b;` so every odd character is shifted 1 to the right allowing you to get the full 0-255 range. – Delta Apr 15 '20 at 19:54
  • @GuineaPig Also, make sure the hex string has the proper size, you might be getting 4/5 digits instead of six depending on the ints, might need to add some padding 0s. – Delta Apr 15 '20 at 20:04