If you’ve looked at the crowdsourced art experiment you may have noticed a little color picker on the page. It looks like this:

My Color Picker
If you’ve seen other color pickers (for example in Photoshop, the Office / iWork packet, or even MS Paint) you’ll notice that this one is slightly different. I made it to have property that a lot of other pickers lack: it displays all possible colors on one two-dimensional plane. If you think about it, the other pickers you’ve seen either have an additional slider that changes the 2D plane (e.g. Photoshop or the built-in Windows or OS X one) or they don’t allow you to specify some colors (e.g. the Pantone picker or a lot of the pickers online).
As you know, I’m fascinated with color, especially when there’s math or technology involved. My picker happens to involve both and so here we go.
The color space is three-dimensional, that is, to uniquely identify a color, you have to specify three dimensions. There are many ways to specify a color: the most common one (albeit not the more natural one to understand) is the RGB space: each color is identified by the intensity of pure red, pure green and pure blue components that, when mixed together additively, construct the desired color. I emphasize additively because when we think about “mixing” color (when we paint with oil or watercolor) we don’t actually compose color the same way our eye does. In the RGB space, there are three numbers you specify for each color: and so yellow can be defined as (1.0, 1.0, 0.0) because it consists of max intensity red and green and no blue. Violet (like the color of this flower) can be defined as (0.6, 0.3, 0.7).
Similarly, there are other ways to describe a color: the HSL space, that I find fairly intuitive, describes a color by specifying its hue (the location on the rainbow), its saturation (how vibrant is the color) and lightness (how bright it is). Again, three dimensions (why the color space is three-dimensional is an interesting question…).
This fact makes it hard to design user interface elements that allow you to pick a color (color pickers): the screen is two-dimensional so you either need a slider or some other way to change the third dimension, or you will see a selection of all colors. Being a visual person, I wanted to have a picker that displays all the colors at once, without some stupid slider.
My first attempt took advantage of the fact that on a computer, every measure is discrete (there is no such thing as infinity in computing) so I can collapse the three dimensions into two simply by cleverly rearranging where each colors should be placed. Assuming that each color component has 256 degrees of intensity (which is the case in computer screens these days), we can list all colors, for example
(0, 0, 0), (0, 0, 1), …, (0, 0, 255), (0, 1, 0), (0, 1, 1), …, (255, 255, 255)
We can now map the sequence into a two-dimensional one, for example
(0, 0), (0, 1), …, (0, 4095), (1, 0), (1, 1), …, (4095, 4095)
The problem, however, is that we want the mapping to be smooth, i.e. ideally we would like nearby pixels to have similar colors, and the mapping above (and in fact most mappings) won’t guarantee this.
This is where math comes in handy, specifically the field of space-filling curves. I kept one dimension (say, the blue component)–that will be my X coordinate of the resulting picker. For the other, I used a Hilbert-like curve to collapse the green and red components into one Y coordinate. A nice thing about Hilbert curves is that they are somewhat smooth: in this picture, if you pick two neighboring points they are likely to be close to one another on the curve. I’ll leave as an exercise for the reader to determine the actual expected Euclidean distance in color intensity for randomly picked two neighboring points on a Hilbert curve.
Well, such was the first experiment. The resulting “color belt” was very long (because collapsing two dimensions into one makes it a very long dimension!) and the lack of smoothness was pretty obvious (click to view the full image):

My first approach to create a two-dimensional complete color picker
I then took the belt and made it into a ring, by “curving” the long dimension around (to take advantage of the fact that the circumference gives me 2π more space than the radius:

The color ring
Besides looking very Tolkenian, the ring has a pleasing æsthetic to it. Still, it’s somewhat hard to pick out the color you want because the colors are fairly scattered (if your mouse if off by one pixel you may be picking a totally different color).
The next approach was to be a little smarter with the choice of dimensions. Instead of picking one of the components to be one dimension and try to collapse the other two, I chose the light intensity of a color as the horizontal dimension and then collapsed all colors of a given intensity into the vertical dimension. The advantage of this approach was an increased smoothness: all colors along a vertical line had the same intensity; and because the intensity function is linear in the values of R, G and B (it’s a weighted average of the red, green and blue intensity), the colors on a horizontal line are all similar.
I also varied the order in which colors would be placed on a vertical line, based on a heuristic of the R, G and B component. Some of the choices gave very interesting results. For example, if I plotted each vertical line based on the lexicographical order (sort by R, then G, then B), I got a picker that looked like this:

Intensity-based picker; pixels ordered lexicographically (R, G, B)
I got really interesting results when I made the heuristic slightly more complex: for example, if I ordered the pixels by the value of the sum of squares of the colors, I got

Intensity-based picker; pixels ordered by R^2+G^2+B^2
Finally, in order to bundle similar colors together (i.e. have fewer “boundaries” where neighboring colors differ significantly at the expense of more pronounced boundaries), I used a heuristic that “favored” one component over another. The image on the right, for example, orders pixels like this:
- In first order, pixels whose blue component is higher than their red component, appear higher in the image
- Then pixels whose green component is higher than their blue component
- Finally pixels whose red component is higher than their green component

Intensity-based picker; pixels ordered based on prevalent component (two different heuristics)
The little picker at the very top of this post is a slightly massaged (reduced and despeckled, to make picking more accurate) version of this approach with a lexicographical order of pixels. I also added a pure gray gradient on the side–even though the picker itself contains every shade of gray, they are scattered throughout the image. If you’re interested, here is what the picker looks like if I order the pixels by saturation, it looks… phantasmagorical:

Intensity-based picker; pixels ordered by saturation
Source code for all color picker generators:
- Color belt and color ring generator: ring.php (it generates a PNG file, so redirect the stdout to a file, say output.png)
- A useful cheatsheet of color conversions (source unknown): colorConversions.txt
- Layered color picker: picker.c (if generate a PBM file that Photoshop/ImageMagick can read, so redirect the stdout to a file, say output.pnm)