I thought about how I could produce an icon with the maximum number of possible colours, but in a somewhat pleasing way.

When I decided to start making something like this, I fiddled with numbers a bit, and figured that 21³ = 9261, which is just short of the 10000 pixels available in a 100×100px userpic. So with three colour components (red, green, and blue), I could divide up the range from 0 to 255 into 20 more or less equal steps to get 21 values.

Since 255/20 = 12.75, that ended up being steps of 12/13/13/13.

As for the pleasing way, I thought of two parts. The first is in what order to use the colour triples I would generate, and the second how to arrange that list in the two-dimensional userpic.

The obvious way would be to simply go from 0 to 255 along each axis, but I would have needed three axes for that. Sorting by hue or something like that was a little beyond me, and simply sorting the triples lexically wouldn't have been that great, either, I thought.

Then I remembered binary reflected Gray codes, where each subsequent value differs from the previous one in exactly one digit, and the difference is exactly ±1 (so no overlap like from 299 to 300 where all three digits change simultaneously). So I read up the Wikipedia article and how to generalise Gray codes to bases higher than 2, and made up a 21-ary reflected Gray code with three digits, ranging from 000_{21} to KKK_{21}. (K_{21} = 20_{10}.) (You will see that the Gray code produced in this manner is not cyclic, since you can't get from KKK to 000 by changing just one digit, but that wasn't important for my purpose since the start and end point wouldn't be adjacent in the userpic anyway.)

The next issue was how to arrange that sequence on the userpic. The obvious way was all values, in order, but that ran afoul of the fact that 21³=9261 is not a square number—nor is it divisible by two number which are both less than 100. But 96²=9216 is just a bit smaller than 9261, and is not only square but nearly the square of a power of two (3×2^{5}), which seemed pleasant to me.

So I decided to remove 9261-9216=45 codes from my list; since that's 5×3×3, I decided to remove all those which had a red component (before normalisation, on a scale of 0 to K) of 1 2 3 4 5 and a green and blue component of 1 2 3 (since dark colours tend not to show as much difference anyway, I thought, I'd chop off at the bottom end of the scale, while preserving complete absence of colour, i.e. a component value of 0).

So now I had a list of 9216 values. I tried just dumping them one after the other but got a "banded" effect which I didn't find particularly pleasant. And since 21 doesn't exactly divide 96, it wasn't even that symmetric. And the adjacency effect of the Gray code was lost once you ran off the end of one row and went all the way back to column 0 on the left. (I considered using boustrophedon to mitigate that a bit, and also briefly considered a spiral arrangement, but decided against it in the end.)

Then I remembered xkcd's famous Map of the Internet, which uses "a fractal mapping which preserves grouping", which I thought had a rather pleasing sort of symmetry.

That works well on squares with a side length of 2, 4, 8, 16, … (the example had a side of 16, since it had to show 16²=255 blocks), since the pattern is based on a 2×2 unit. I had a side length of 96, which is not an exact power of two; fortunately, I quickly figured out how to make a 3×3 unit which had its start and end positions in the same place as xkcd's 2×2 unit. Now I could simply take that unit and rotate and reflect it to make larger 6×6 squares, which could then be similarly rotated and reflected to make 12×12, 24×24, 48×48, and finally the 96×96 square, with (0, 0, 0) at the top left and (255, 255, 255) at the top right, and all the other values somewhere in between, with the path winding like a snake convoluted at several, increasingly-smaller levels to show self-similarity.

What I found interesting was that the result showed some apparently-jarring steps of colour; when I looked it more closely, the ones I examined were always ones where the green component changed. And even though it changed by the same amount as the others (i.e. 12 or 13 steps), it was more obvious than when the blue or red component changed, proving again that the human eye is more sensitive to greens.

Aside: perhaps I could have re-done it with not 21 values for each component but with more for green than for red and blue—say, 16 each for red and blue but 32 for green, for a total of 8192 values, or 17/17/33=9537—or 10/10/100=10000. But that was after I had already put a lot of effort into the thing, so maybe another time.

Hm, I'd have to see what side length to use; 9537, for example, has the nice property that the steps are 16 and 8 except for the last one, but falls between 97²=9409 and 98²=9604 by 128 and 67, respectively. Hmm... 128. What a tempting number. 2^{7}, i.e. 4*4*8, so perhaps similarly drop values of (1,2,3,4) out of 17 for red and blue and (1,2,3,4,5,6,7,8) out of 33 for green? Which is even roughly the same proportion once you scale from 0..16/0..32 to 0..255…. Tempting. Even though 128/9537=1.3% is more than the 45/9261=0.5% I had to drop earlier.

On the other hand, 97 is not such a nice round number that I could re-use my fractal pattern for (in fact, it's prime, so it doesn't even lend itself to *any* subpatterns), and dropping 9537-9216=321 values=3.4% would probably be too much to be worth it.

Wait, I just realised that 9216=16*16*36... and 15 exactly divides 255 (255 = 15*17), so 16 values gives step values of 17 exactly. Ooh. Though the 36 is just too bit, since 35 would give 34 steps, which is 2*17, so each step would be 15/2 ~ 7.5 each. While 36 gives 35 steps of ~7,2857142857... = 7 2/7 each, or perhaps 7/7/8/7/7/8/7. Still. Tempting.

So, anyway: I give you my fractal 9216-colour userpic!

And due to the fact that adjacent pixels typically have a similar colour, it even compresses fairly well. (Certainly a lot better than the random-colour userpic I also generated, based on data from random.org.)

What do you think?