Jump to content
  • Advertisement
Sign in to follow this  
osh

little fun with bits

This topic is 4897 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys! Right now, I'm coding some simple graphical filter (Gaussian blur to be exact). I have my image in memory and I need to take a pixel, the one left to it and the other one right to it. Sum these pixels like left + 2 * current + right and divide all by four. And here goes my question. As I have 24 bits per pixel I wonder if I can sum/multiply/divide those pixels as 4 bytes integer (with mask removing the last one byte that goes for next pixel) or I have to extract the colors? Thx in advance Ondra
//can I do this?
current = (current & 0xFF000000) | ((left & 0xFFFFFF) + 2 * (current & 0xFFFFFF) +  (right & 0xFFFFFF));

Share this post


Link to post
Share on other sites
Advertisement
No. You can't do that because the results of math operations will cross into adjacent colors. For example,

00 00 ff (bright blue) * 2 = 00 01 fe (slightly darker blue with a little green)
00 03 00 (very dark green) / 4 = 00 00 c0 (bright blue)

Share this post


Link to post
Share on other sites
If you don't have mmx or want a portable version using one of the following might be an option.
Loosing some precision:

New = (Left & 0xfcfcfcfc) + ((Current & 0xfcfcfcfc) << 1) + (Right & 0xfcfcfcfc);

Or more accurate:

LeftRB = Left & 0xff00ff;
LeftG = Left & 0x00ff00;
CurrentRB = Current & 0xff00ff;
CurrentG = Current & 0x00ff00;
RightRB = Right & 0xff00ff;
RightG = Right & 0x00ff00;
New = (((LeftRB + CurrentRB + CurrentRB + RightRB) >> 2) & 0xff00ff) | (((LeftG + CurrentG + CurrentG + RightG) >> 2) & 0x00ff00);

It's also quite useful for blending etc since you can do a multiply after splitting into 0xff00ff and 0x00ff00. You can easily extend this to ARGB with some additional shifts.

Share this post


Link to post
Share on other sites
eq knows the stuff.

Your idea as you may have already noticed doesn't quite work, but this will:
redblue = (((left & 0xFF00FF) + ((current & 0xFF00FF)<<1) + (right & 0xFF00FF))>>2) & 0xFF00FF;
green = (((left & 0xFF00) + ((current & 0xFF00)<<1) + (right & 0xFF00))>>2) & 0xFF00;
current = redblue | green;

However this trick is more useful for 32-bit where data is aligned to 4-byte boundaries. It may not be any faster than operating on single bytes for 24-bit.
i.e.
unsigned char *inPixels, *outPixels;

*outPixels++ = (*(inPixels-3) + (*(inPixels)<<1) + *(inPixels+3)) >> 2;
inPixels++;

repeat for red, green and blue.

Try both and if both work, pick the faster one.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!