Thursday, July 8, 2010
Motoring through the Color Cube
So you're writing an app about color, and you want to let your users pick any color that they want. How do you do it? A good solution is surprisingly elusive; in The Mind of Monet, I tried out four different methods of color selection before finding something satisfactory.
And why is it so hard? The easiest way to let a user choose color is surely to give them a spectrum of colors to choose from; something like this:
You show this spectrum of color somewhere on the screen, and wherever the user taps on the spectrum becomes the color of their choice. Easy, intuitive, obvious. It's the first solution that I used for The Mind of Monet, and it didn't work.
As I learned, there are two problems with this approach. The first one is straightforward: on an iphone/ipod touch, there just isn't that much screenspace to work with. Devoting a third or less of the screen to a color spectrum and asking the user to choose a specific color is like asking them to play a harpsichord sonata with boxing gloves on.
To understand the second problem, you need to know a bit about how color works on an iPhone. When a developer defines a color to use in an iPhone app, the most common method is to provide three numbers. Each of the three numbers corresponds to a different color; there is a number each for red, green, and blue. For each of those three colors, a value between 0 and 255 is allowed; choosing 255 for all three gives pure white, while 0 for all 3 gives pure black. The many other possible combinations represent every hue that an iPhone can produce; 150 red with 123 blue and 10 green would be a nice purplish shade, and so on.
And here we come to the second difficulty. With three different colors to set that have 256 possible values each, the total number of potential colors is 256 * 256 * 256, or 16777216. That's almost seventeen million colors, but there are only around 15000 pixels on an iPhone screen. Even if you devote the entire high-resolution screen of an iPhone 4 to color, using one pixel per unique color, you still won't be able to represent anything close to all the possible colors. Those programs that show you a spectrum of colors and allow you to choose one? They're really showing you a tiny subset of available colors, trimmed down to a fragment of the color range that the hardware provides.
So how do we let the user easily and intuitively choose any color that they like, providing simple access to the 17 million colors available? One way to think about the problem is in terms of the space of possible colors. With three different colors to set, the color space is like a cube, with each side of length 256. How do we let the user drive around inside that cube? Should we try to represent that 3d cube in 2 dimensions, and if so, how?
The solution that I finally settled on was inspired, as one might expect, by the process of actually producing a real painting. A working painter is expert at mixing colors together to achieve a desired result; a touch of yellow, a blob of green, maybe some white to get the color of grass. For the Mind of Monet, I decided to duplicate this ability to mix different amount of different colors together, to produce (literally) over a million different possibilities in a single color result.
By giving the user a palette of 6 colors to mix together, it's possible to provide the ability to navigate to any place within the 256 x 256 x 256 color cube. When you add a little bit of black, you drive down the values of all three of red, green, and blue at once. When you add blue, you push up just the blue value while gradually pushing out the others, etc. I made the palette so that the longer you hold down a given color, the more of that color that you add to the result. Just a tap on a color would be a nudge of 1 point in that direction; holding the button would add more and more, until eventually you would have a pure version of the color that you were holding down.
When I tested this approach with users, I ran into another challenge: people aren't accustomed holding down a button to get more of a color. When you see a palette of colors, you expect to tap green once, and have chosen green, then tap red, and have chosen red. In other words, while the painter might expect to mix colors, the computer user sees six color buttons, and expects to have only six colors to choose from.
I've addressed this problem in two ways: first, I added a paintbrush, which travels from the color result to the color button when it is pressed. Some animation added to the action of pressing a button will (I hope) cause the user to do less, tapping, and more pressing and holding (perhaps surprisingly, so far this seems to help). Second, I've added a tutorial that appears when the app first starts; the first order of business in the tutorial is to describe how to mix color. Nobody (myself included) likes to spend much time on a tutorial, but since color mixing is the first subject mentioned, there is at least a chance to some users will read it.
If the problem of users not knowing to hold down a color button persists, then I may be forced to recognize the actions of a confused user and pop up some information about how to set color. Sniffing out user intent and popping up information is a little too close to Clippy for comfort, so I'd rather avoid this if at all possible.
Posted by Ed at 2:48 PM