Playing with color

Setting the stage

Some time ago, I found something on the internet that I thought was pretty nifty: http://whatcolourisit.scn9a.org/. If you'd like to take a moment to check it out, go for it; it won't take long.

In case you were lazy (in which case, my hat's off to you), or possibly confused at what it was, the idea is cute: treat the time components as hexidecimal HTML color specifiers, and make the background whatever color is currently indicated by the time. To understand HTML color, all you have to know is that there are three "channels", for red, green, and blue. Each channel is described with a hexidecimal number from 0 to FF (0 to 254 in regular decimal). The numbers are 0-padded, meaning that each channel has two hex digits for it, even if it's less than "10" (that's 16 in regular decimal). Hex digits are typically written with a prefix of "0x", so the previous hex digit ("10") would be written as "0x10", and all further hexidecimal values will be written that way, unless they're part of an HTML color specification.

What Colour Is It treats the hour as the red channel, the minute as the green channel, and the second as the blue channel.

A brief digression into how color works in HTML, concretely

To put this concretely, to make a pure, 100% saturated red color, the value of the red channel must be 255 in decimal, or, 0xFF in hex, while the green and blue channels' values must be 0 (or 0x0 in hex). The HTML color specification for that pure red is "#FF0000". To make pure green, "#00FF00", and for pure blue, "#0000FF". Black is #000000 and white is #FFFFFF.

OK, now that we're all highly trained experts in HTML color, we can see what's going on at What Colour Is It. You might notice that the lightest color that will ever be displayed there is #235959, which looks like this:

the brightest colour

A first pass at a better way to treat time as color

If you're thinking it's not very light, you're right. It's nowhere near #FFFFFF. Whole swaths of the RGB gamut are missing; there's some obvious room for improvement. Enter the NebCorp ColorTime Service, a NebCorp Service brought to you by NebCorp™:

http://colortime.nebcorp.com/

If you'd like to take a moment to check that out, I encourage you to do so; it's WAY better, if I may be immodest.

Now that your life is immeasurably improved, here's what's going on there. Like What Colour Is It, ColorTime treats the time components (hour, minute, second) as RGB color values. However, ColorTime spans the entire HTML RGB gamut, from #000000 to #FFFFFF. The way it does that is by mapping the range of temporal values (hours go from 0 to 23, seconds and minutes go from 0 to 60) to the range of 0 to 255. However, the gamut there is sparsely sampled: there are only 24 possible values for red, and 60 possible values for green or blue. If you view the source on http://colortime.nebcorp.com, you can see the Javascript functions that do that mapping. You can also check out the git repo at https://github.com/nebkor/colortime.

If you were to lay out all the colors from ColorTime in a line, from midnight to 11:59:59pm, it would look like this:

colortime rgb

You can clearly see the hours there, and even the minutes are discernible. The base color of the hour gets more red as the day progresses, blue dominates in the beginning of each hour as the seconds climb in each minute, and green asserts as the minutes climb in each hour.

I was pretty pleased with it; it was my very first dynamic web page using Javascript! Until I got a feature request.

An adventure in cylindrical colorspace

Shortly after I made ColorTime, my friend Brian said to me, "You might want to look into using HSV or other colorspaces, and see if you can make the transitions smoother."

I felt I had a pretty solid grasp on the RGB color system that I was using, and though I knew of the existence of alternate color representations, like HSV or CMYK, what exactly "HSV" meant was not something I understood really well. So I decided to read some Wikipedia and write some code to figure it out.

The Wikipedia article on HSV is really informative; if you're interested, check it out. But basically, the letters in HSV stand for hue, saturation, and value. Hue is what you think of as "color", saturation is how "colorful" it is, and value is how "bright" it looks. Conceptually, the hue in HSV can be thought of as the rim of a colored circle that starts at one point as red and smoothly goes through the full range of RGB colors around the circle until it arrives back at the starting point, where it simply transitions smoothly back into red. If you were to cut that circle and stretch it out into a line, you'd have a color progression like this:

hue around the clock

In that image, both saturation and value are held constant at 100%. Hue varies in value from 0 to 359, and is the angular distance from the starting point of the circle, in degrees.

Smooth move, Exlax

That's a bunch of pretty smooth transitions from color to color, as you can see. I could, if I wanted to, convert the time from the "hh:mm:ss" format to the number of seconds since midnight, and it would be easy to map that number into the range of valid hue values. There are 86,400 seconds in a day, so I just need to translate that into a number from 0 to 359. See? Easy!

But one thing I like about the current ColorTime is that all the knobs on the color-making machine are twiddled by all the parts of the time-showing machine, in a way that you can visually decompose. However, in this color timeline, there's no good way to see the individual effect of, say, the minute component of the time; it's all just rolled up into the daily epoch and turned into hue.

Fasten your seatbelt, it's going to be a bumpy ride

Given that there are three temporal components and three color components, there are five unique ways to get a color by mapping one temporal component to one color component. Here's what all of those look like:

hour becomes hue, minute becomes saturation, second becomes value:
hsv

hour becomes value, minute becomes hue, second becomes saturation:
vhs

hour becomes saturation, minute becomes value, second becomes hue:
svh

hour becomes hue, minute becomes value, second becomes saturation:
hvs

hour becomes value, minute becomes saturation, second becomes hue:
vsh

hour becomes saturation, minute becomes hue, second becomes value:
shv

Oh man, none of those are smooth AT ALL!

Now what?

Well! Honestly, that was mildly surprising. Compared to the RGB system, all the piecewise conversions of time to color using the HSV system are less smooth. On the other hand, I like the way the "hour->hue, minute->value, second->saturation" timeline looks a little better than the current RGB conversion. So I'll probably add a couple HTTP endpoints to ColorTime to support that "hvs" system as well as the smoothly-varying "time->seconds->hue" method.

UPDATE: my good friend Allen Hemberger pointed me to the the human friendly HSL system, so I'll be playing with that soon.

But really, this was a fun little way to make pictures with Racket. You can see the tiny program I wrote to generate the images from this post at https://github.com/nebkor/colortime/blob/60998e31cfea798bf13f847a45c6b58a7a03b1c5/make-colors.rkt, though I apologize for the lack of comments. I got pretty proficient with thinking about the higher-order functions like for/list and friends, which was fun as well. And finally, I now feel that I actually understand what HSV is and how it relates to RGB.

I hope this you enjoyed reading this as much as I enjoyed writing it!