Shading an RGB value

Started by
4 comments, last by DarkMatter2008 15 years, 2 months ago
Hello All, I'm trying to shade and rgb value by a value

int red = sha << 16;
int green = sha<< 8;
int blue = sha;

color -= (red | green | blue);
This seems to work, until one of the colours reaches is lowest limit, i.e. when red is out it'll rollover and go bright green or blue. Is there some sort of fancy mask to prevent this? Thanks In advance.
Advertisement
You would have to subtract from each component of color separately, and clamp to zero.
What Zipster said.

You could write a color class, which implements a subtraction operator (that is, if you are on c++, otherwise you would write a function "subtract()"), which internally does subtraction on three seperate values. Or if you rely on all components being in a single value, you have to decompose it first (using shifts and bitand's).

Upon subtraction, the easiest way is to convert each component into a signed integer of a bigger bitsize, perform a subtraction, clamp it to an upper/lower limit, and cast it back into the components/the color value.
I'm not writing in OO i'm afraid. Is there a nice clean way to extract the RGB elements and clamp them to zero?
Bitwise ops, just revert what you have already used:
// your codeint red = sha << 16;int green = sha << 8;int blue = sha;


First, a struct could be handy:
// r,g,b are supposef to represent value between 0 and 0xFF.// We have declared them as integers in order to take "over/under-flow"// into account.struct RGB {    int r, g, b;};



Then, to get the components:
assert (sizeof (int) > 1); // But you can bet on that.// How we would decompose:RGB rgb = {  (sha >> 16) & 0xFF, // The value 0xFF is 11111111 in binary,  (sha >> 8)  & 0xFF, // and with the bitand we filter out every bit  sha         & 0xFF  // that is on the "left" side};


Now we are going to define a clamp function:
void clamp (RGB *rgb) {    assert (0 != rgb);    if (rgb->r < 0) rgb->r = 0;    else if (rgb->r > 0xFF) rgb->r = 0xFF;    if (rgb->g < 0) rgb->g = 0;    else if (rgb->g > 0xFF) rgb->g = 0xFF;    if (rgb->b < 0) rgb->b = 0;    else if (rgb->b > 0xFF) rgb->b = 0xFF;}


Next, an example function to add colors (which will use the clamping function):
void clamp (RGB *target, const RGB *lhs, const RGB *rhs) {    assert (0 != target && 0 != lhs && 0 != rhs);    target->r = lhs->r + rhs->r;    target->g = lhs->g + rhs->g;    target->b = lhs->b + rhs->b;    clamp (target);}


At last, you can use your three rgb values and shift up what you need:
RGB alpha, bravo, charlie;...add (&alpha, &bravo, &charlie);uint32_t final = (alpha.r << 16) | (alpha.g << 8) | alpha.b;



Code is in plain C. Not tested.
Thanks for that, it was really really help full.

I modified one of the functions because I don't really need so many stucts lying around.

void clamp (RGB *lhs, const int shade) {	lhs->r += shade;	lhs->g += shade;    lhs->b += shade;    clamp (lhs);}


Thanks again :)

This topic is closed to new replies.

Advertisement