Monthly Archives: April 2010

How RGB is related to HSV, and how to implement hue shifting on the iPhone

Last weekend, I wrote some code that shifted hues in existing colors. To do that, I needed to improve my understanding of hue, saturation, and lightness. I had to go on a journey of learning and trustmypaper educational service helped me a lot! So, I thought I’d share my rainbow voyage with you here.
I started by poking around in Photoshop. If you’re familiar with Photoshop, you may recognize this dialog:

If you move around the Hue slider, your image changes color without changing either saturation (which can be described as ‘colorfulness’, sort of) or value (lightness). That is exactly the functionality I wanted to implement. In Photoshop, it’s also fun stuff that can make your photos look psychedelic.

Then, there’s this guy, the Color Picker:

To pick your color, you click around in the box on the left and move the rainbow slider up and down. The number-containing boxes in the middle show you the RGB (red green blue) values of the color currently specified, which is handy. The rainbow slider is a hue controller, and the big box on the left represents lightness on its Y-axis and saturation on its X-axis.
When you sit down to code something like this, though, you can’t manipulate the hue directly like that, at least not on the iPhone. You can’t just say “give me this existing color’s hue” and then use that to compose a new color. Whether you’re using UIColor, CGColor, or cocos2d’s ccColor3B, the only way to manipulate the hue of an existing color is via RGB. Thus, you need to figure out how RGB affects HSV (hue saturation value/lightness).

Moving the hue slider in Photoshop’s color picker and noting the RGB value changes is a good way to do this. Try it, and you’ll notice that among the RGB values, there’s always a constant highest number, a constant lowest number, and a variable middle number.

Let’s say the color you start off with has an RGB of 57181-107 (a mildly-bluish green). You can move the hue slider anywhere you want, but two of the RGB values will always be 57 and 181. If you slide it toward the orange spectrum, you’ll end up with something like 181-107-57. 181 and 57 are still in the mix, yet it’s an entirely different color.

When moving the hue slider, the limits remain constant because changing the upper and lower limits will affect the lightness and saturation of a color. If you move the cursor in the saturation/lightness color panel, however, those limits will change.

Lightness

On a display, if you max out red, green, and blue, the result is pure white. It follows that raising the upper limit among the RGB components of a given color will move it closer to white, whereas lowering the lower limit will move it further away from white. “Moving a color further away from white” is also known as “darkening a color.”

Saturation

Saturation is also affected by the upper and lower RGB limits, but by the two limits’ relative distance from each other, rather than by the limit’s absolute values. In RGB terms, gray occurs when each of the components’ values are close to one another. 177-171-161 is a kind of gray, for example. When all three components of a color have matching values, as in 177-177-177, that color is said to be totally desaturated.

Conversely, the further apart the RGB components are, the more saturated the colors become. e.g. 255-112-17 is a very intense orange. 255 and 17 are about as far apart as you can get.

Hue

If we want to change the hue while freezing saturation and lightness, we can’t change the upper and lower limits, as explained above. That leaves us just the following:

1. We can change the variable middle value. e.g. 112 in a color like 112-67-233. If we change 112 to 150, we get 150-67-233.

2. We can’t change the upper and lower limits, but we can swap their positions. e.g. In 112-67-233, we can move 67 and 233 and get
67-233-112.

Now we know how to change the hue without messing with saturation or lightness, but we’re changing it haphazardly. To find out how to move the hue along the spectrum the way the Photoshop slider does, look at the RGB value changes that happen when the slider is slowly moved in the red-to-blue direction. You’ll see that:

1. One value (either R, G, or B) changes at a time.
2. That value is either moves up until it hits the upper limit, or it moves down until it hits the lower limit.
3. Once a value hits a limit, that value stops changing momentarily, and a different value starts moving.

Here’s a graph of the changes in the RGB values as the color is moved along the spectrum:

(I apologize for the graph’s crapulence. I bet you there’s a good version of this somewhere on the web, but it wasn’t on the first page of search results, so I just scriggled this out.)

The lines represent the amounts of R, G, and B components that are present in each point along the spectrum. The vertical bars at the top are the colors that (approximately) result from those RGB combinations.

The graph shows the following behavior: For each component (R, G, and B):

– If the component is not at the the lower limit and the next component (e.g. the next component after the R component is G) is at the upper limit, that component will descend.

– If the component is not at the upper limit and the next component is at the lower limit, that component will ascend.

– Otherwise, that component doesn’t change.

I’m sure there’s some clean mathematical formula that describes this, but I haven’t done any real math in like twelve years, and now my math organ is shriveled and useless. So, you’ll have to live with the algorithm.

Implementation

Once you know the above, implementation is fairly straightforward. If you want an example, though, here’s my cocos2d-oriented implementation in Objective-C on github.

OGColorTools contains the code that does the color shifting. The meat of the code is in the method color:shiftHue:inDirection:. OGHueShiftExampleLayer is a simple example layer that creates a sprite and shifts its color every time the layer is tapped. You will need to provide your own bitmap and load it into the sprite for this to work.

Enjoy your hue shifting!


Embiggening

I went to the store yesterday to try out the iPad, and I (more or less) impulse bought it on the spot. Technically, the iPad held no surprises. Experience-wise, it did.

With no further ado, the surprises, enumerated:

1. Browsing the web on the iPad is quite possibly better than browsing the web on a computer. Technically, it’s just like browsing the web on the iPhone. Except that the viewport is much bigger. This is a simple, simple change that inspired many a “it’s just a big iPhone” comment. When it comes to browsing, those comments hold true, in a technical sense. Yet, the embiggening really transforms the experience.

On the iPad, web pages look just like a web page would on your MacBook (or Dell, Lenovo, Alienware XL2bunchofnumbers or what have you). On the iPhone, web pages looked truer to the html than they did on other phones, but they were still, of course, miniaturized.

So, browsing on the iPad looks the same as it does on a computer. Then, what’s the difference? The method of interaction.

On a computer, you move your mouse to links and other interactive objects then click on a mouse button to make things happen. On the iPad, you just touch them. Also, you can put your finger directly on the page and push it up and down. Again, this is a small difference on paper that changes the experience wholly. It feels more intuitive. For me, it feels better.

(Incidentally, I’ve had three different people tell me that their two-year-old kids quickly learned how to use an iPhone. The whole “touch an object, get a reaction” way of operating is what allows this to happen. It’s difficult for someone that age to understand that moving a mouse and hitting keys with certain markings causes a change on the screen, but they do understand the idea of things reacting when you touch them.)

2. You know how there’s a lot of iPhone development work these days centered around creating an iPhone app version of a web site or application? That’s not necessary for the iPad. There’s plenty of space, so most web stuff does not need to be re-presented in smaller bites.

The best way to use Facebook on the iPad is not through a Facebook app, but through Safari. (Well, probably – I haven’t tried Facebook Ultimate.) The best Twitter application for the iPad is Brizzly, through Safari. Flickr.com is better than the Flickr app.

3. The same thing I said above about web browsing, except with games. I thought Final Fantasy I for iPhone was well-done, but there’s no way you can avoid some cramping in a phone game when porting a game with a certain level of complexity. On the iPad, it’s spacious and detailed. You can touch things without worrying about accidentally hitting the wrong thing. It’s a better game than it was on NES or Playstation. To sort of get you an idea of how it looks and feels.

(I tried to play it with one hand while holding the camera with the other, and my girlfriend walked in in the middle of it and made fun of me for doing this. It is also upside down. Yet, I think there’s still a chance that it’ll help you get the idea.)

Final Fantasy I is just a remake of an old game, so it might seem like it’s not that relevant that it’s good on the iPad. (Although it did debut as the top grossing game the week it was released, so a lot of people out there do care about remakes.) However, if simply giving a game five times the area improves things this much, it’s a great sign for future games made specifically for the platform.

4. The keyboard is rather good. I’m not going to write a novel on it, nor even a blog post, if my MacBook is nearby. However, it’s perfectly fine for writing tweets or typing terms into a search field. Being able to spread your fingers out is a big deal.

The iPhone touch-based user interaction model was a huge step forward. But in some ways, the iPhone’s phone-sized frame muted just how huge it was.

In a way, the iPhone is like Jigoro Kano, the creator of judo. He was innovative and capable, but being 5′2″ and somewhat of a pacifist, there were certain things he just couldn’t do. The iPad is like Masahiko Kimura, a much bigger and stronger judoka that defeated fighters all over the world, illustrating more clearly to the world what Kano’s techniques could do.

Of course, spending much of his life traveling around to beat people up limited Kimura in ways that Kano was not limited, in the same way that the iPhone can go many places that the iPad cannot.

(Wow, that post took a pretty weird turn at the end. OK, I’m done here. Excelsior!)