Can I also ask for help here?
I don't want to create an extra topic.

I have got a 16-bit color and want to adjust the lightness of the color with a function like this:


Code:

color_t changelight(color_t color, unsigned char val)
{
   //change red, green and blue with the same value
}


It should accept val >= 0 && val < 256, so I would have to act with percents or something similar...

I really don't have an idea how to do this in a fast bitshifting way Sad
My approach:

Code:

unsigned char red, green, blue;
red = (color & 0b1111100000000000) >> 11;
green = (color & 0b1111110000) >> 5;
blue = color & 0b1111;

leeway = 0xFFFF - (~(red & blue & green) & (~(~red & ~blue & ~green));
//get the leeway of the darkness (probably wrong? No idea here.)

red += (val - 0x88) / leeway;
green += (val - 0x88) / leeway;
blue += (val - 0x88) / leeway;

I don't think that this works.
Split from Flyingfisch's thread because I think this warrants in-depth discussion.

First off, you're not very clear about how exactly you want to adjust the "lightness". What's the meaning of 'val'? Sounds like you want to set the color's overall tint to some relative value, but how exactly that's supposed to work isn't clear.

Anyway: A "pure" approach to this problem would probably covert from RGB to HSL color models. From there, you can set an absolute saturation and convert back. This is slow but accurate. If you want a simple linear scale, then it's basically a matter of determining what you must add to make the most intense channel have a maximal value. In either case, you can't get around needing to unpack the channels.

In musing on vectorized operations, you could save needing to unpack one channel in addition and subtraction operations by extracting the middle channel and doing it alone, while the others remain packed. For example, if we were to add 0x10 to each channel:
Code:
color_t c;
// Extract mid-packed channel
unsigned green = c & (0x1F << 5);
c &= 0xF81F;
// Add
c += (0x10 << 11) | 0x10;
green += 0x10;
// Clean up and recombine
c &= ~0x07E0;
green &= 0x07E0;
c |= green;
By extracting the middle channel we don't need to be concerned with potential carry-out (aside from it probably making the wrong color), since it's guaranteed to be stopped by the (now vacant) middle channel.
That scheme probably isn't actually useful, but it might be handy for vectorizing operations in some unusual situations.
'val' is the value of the brightness, 0 should be the brightest possible color, 255 the darkest.
And I really didn't know how to do this, that's right. I operated with just 2 colors (Black & white) before Smile

Quote:
This is slow but accurate

I don't need the most accurate way, it should be fast.

The vectorized way seems to be useful.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement