views:

181

answers:

2

Making a Blackberry app, want a Gradient class. What's the most effective way (as in, speed and battery life) to interpolate two colors? Please be specific.

// Java, of course
int c1 = 0xFFAA0055   // color 1, ARGB
int c2 = 0xFF00CCFF   // color 2, ARGB
float st = 0          // the current step in the interpolation, between 0 and 1

Help from here on. Should I separate each channel of each color, convert them to decimal and interpolate? Is there a simpler way?

interpolatedChannel = red1+((red2-red1)*st)
interpolatedChannel = interpolatedChannel.toString(16)

^ Is this the right thing to do? If speed and effectiveness is important in a mobile app, should I use bitwise operations?

Help me!

A: 

Updated my answer (found a better way):

The following technique will lose 1 bit precision per channel, but it's extremely fast, since you won't have to split the colors into channels:

int color1 = ...;
int color2 = ...;
int interpolatedColor = ((color1 & 0xFEFEFEFE) >> 1) + 
                        ((color2 & 0xFEFEFEFE) >> 1));

So you first AND both colors by FEFEFEFE. This removes the last bit per channel (reduces precision, as I said). After that, you can safely divide the entire value by 2 (implemented as a right-shift by 1). Then you just add up the two values.

Chris Lercher
The question said pseudocode and bitwise ops expected. I don't know a thing about bit managing. Examples!
navand
This only gives a 50/50 mix, not a configurable 0..1 blend.
Jason Williams
@Jason: Oh, I didn't realize that! You're right... I'll change my answer to community wiki. Maybe it's still useful to somebody...
Chris Lercher
Yeah not exactly what I need. If you find something, please help!
navand
+3  A: 

You'll have to separate channels, but there's no need to convert them to decimal.

For example, if you allow 256 possible gradients:

red = red1 + ((red2 - red1) * stage / 256)

EDIT: Since you said you don't know much about bit management, here's a quick way to split channels:

red = color & 0x000000ff;
green = color & 0x0000ff00;
blue = color & 0x00ff0000;
alpha = color >> 24;

And combining them back:

color = (alpha << 24) | blue | green | red;

From here, the details should normally be handled by the compiler optimizations. If anything, you're looking for the best algorithm.

Raymond Martineau
So how do I separate the channels? Back when I did actionscript, once I needed to do it. I turned the hex value into a string, separated the string into 2 character components, and turned each component back into an integer. I'm sure this is a lousy way of doing it, so please help me here.Also, I need to know if that formula is the best idea or if bitwise ops are faster/better.
navand
Raymond Martineau
you do want to mask the interpolated channels before combining back. the division used to compute the green channel would pollute the red channel with the green remainder (e.g.) otherwise.
Bahbar
thanks for the answer. Now I have the separate channels, but I still need the interpolation thing. Help?
navand
@navand: did you read the first formula ? That's the "interpolation thing"...
Bahbar
I did... I just thought there was a way of doing that formula with bitwise operations, and that doing so would be faster. Am I right?
navand
Wait a second... are you confusing the red and blue channels?
navand
@navand: no you're not right. interpolation is inherently an arithmetic operation. What makes you think bit-wise operation would be faster than arithmetic operations that are natively supported by most processors ? do you really want to implement a multiplier ?
Bahbar
I just had the impression they were...
navand