Writing an HSV Color Picker
Over the weekend I got to the point in one of my iPhone apps where I needed to add a color picker. I quickly discovered there isn’t a standard color picker control for iOS, so I figured I’d write my own.
Color pickers come in all shapes and sizes, depending on platform, UI toolkit, etc. One of my personal favorites is the HSV color wheel, where hue changes by angle, saturation by radius, and the value parameter is edited separately (typically with a slider.)

The basic algorithm to generate the color wheel above went like this in my implementation:
for (y pixels to span -half_height to half_height)
{
for (x pixels to span -half_width to half_width)
{
// atan2 returns the angle from -pi to pi
// radians so we convert to degrees here.
angle = atan2(cy, cx) * 180 / pi;
if (cy < 0)
{
angle += 360;
}
// calculate the current distance from center.
distance = sqrt( (cx * cx) + (cy * cy) );
// calculate the percent of the 'maximum radius' this is.
// max_radius is the lesser value of half_width, half_height.
saturation = distance / max_radius.
// we can now simply convert from HSV to RGB.
color at cx, cy = hsv_to_rgb(angle, saturation, value);
}
}
The 'value' parameter, specified separately, would just be passed in.
The only missing step above is the conversion from HSV to RGB. For that part, I used the algorithm described in the classic reference book, Computer Graphics: Principles and Practice, which essentially breaks the circle into 6 sections of 60 degrees to interpolate the colors in each accordingly. You can find sample implementations here (via Google Books), or here.
Once I got that part implemented, the rest was pretty straight-forward. When the user taps anywhere on the circle, the hue/saturation combination is shown in a preview box, indicating the selected color. Separately, they can touch the 'value' gradient to manipulate the "brightness." I implemented all of the visuals in custom drawRect code after subclassing UIView. I've been playing with overlaying some image 'skins' to make it look a little more robust, but the basic functionality works pretty well.

