🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

16 bit color

Started by
9 comments, last by Ake 24 years, 7 months ago
Everybody new to DirectX seems to have this problem, here is what I use to extract or create the rgb values. Basicly, just add it at the top of your code and your good to go.

#define RED(p) ( p >> pRed ) // Extracts Red Component
#define GREEN(p) ((p & mGreen) >> pGreen) // Extracts Green Component
#define BLUE(p) ( p & mBlue ) // Extracts Blue Component
#define RGB16(r, g, b) ((r << pRed ) | (g << pGreen) | b) // create RGB value

William Reiach - Human Extrodinaire

Marlene and Me


Advertisement
Thanks, but do you have any nice values for
masks and shift, or do you get them from DX?

A good way to do it is to save your DDPIXELFORMAT masks dwRBitMask,
dwGBitMask, dwBBitMask (from GetPixelFormat) in variables, so you
can buildup a macro that will work great with everything.

But what GetPixelFormat does not explicitly return is the number of
bits you need to shift each RGB component to make your 16-bit value.

Well, the DD docs has a neat function that does this for you:

code:
WORD GetNumberOfBits(DWORD dwMask) { WORD wBits = 0;     while(dwMask) {    dwMask = dwMask & (dwMask - 1);    wBits++;     } return wBits;}

What this does is count the number of '1' bits in a mask. So,
a blue mask of 0x001F will return a value of 5 (only 5 bits are set)

Save these mask bit counts in variables too. These are needed to
finally determine how many bits you need to shift each RGB component.

It'll look something like this:
------
DDPIXELFORMAT ddpf;
ZeroMemory( &ddpf, sizeof(DDPIXELFORMAT) );
ddpf.dwSize = sizeof(DDPIXELFORMAT);

surface->GetPixelFormat(&ddpf);

red_mask = ddpf.dwRBitMask;
green_mask = ddpf.dwGBitMask;
blue_mask = ddpf.dwBBitMask;

red_bits = GetNumberOfBits(red_mask);
green_bits = GetNumberOfBits(green_mask);
blue_bits = GetNumberOfBits(blue_mask);

blue_shift = 0;
green_shift = blue_bits;
red_shift = blue_bits + green_bits;

------

That's all you need to do! Now you can reference these variables in
a 16bit macro or function and you are good to go. So use the masks
to extract RGB components, and use the shifts to make a 16-bit color
value.

Don't use constant values directly, it will only make your code less
compatible.

Reaver

[This message has been edited by Reaver (edited November 01, 1999).]

To answer your second quesion, Ake, you need to scale R, G and B to get them in the 0-255 range. The simplest thing is to do another shift:

B = (col & 0x1F) << 3;
G = ((col >> 5) & 0x3F) << 2;
R = ((col >> 11) & 0x1F) << 3;

This doesn't quite work though! It results in these ranges.

R = 0-248
G = 0-252
B = 0-248

Close enough!

Thanks a bunch, guys...
OK, I'm not really happy yet. I'll give you the code first:
USHORT GetColor16()
{
return (USHORT) (( m_iR << m_wRShift ) | ( m_iG << m_wGShift ) | m_iB );
}

void GetRGB()
{
m_iB = ( col & m_dwBMask ) << 3;
m_iG = ( (col & m_dwGMask ) >> m_wGShift ) << 2;
m_iR = ( (col & m_dwRMask ) >> m_wRShift ) << 3;
}

void SetPixelFormat( LPDIRECTSURFACE4 bla )
{
m_dwRMask = ddpixel.dwRBitMask;
m_dwGMask = ddpixel.dwGBitMask;
m_dwBMask = ddpixel.dwBBitMask;

WORD wRBits = GetNumberOfBits( m_dwRMask );
WORD wGBits = GetNumberOfBits( m_dwGMask );
WORD wBBits = GetNumberOfBits( m_dwBMask );

m_wRShift = wBBits + wGBits;
m_wGShift = wBBits;
m_wBShift = 0;
}

Not this looks ok to everyone, then let's try it.
wSurf2[ y * 256 + x] = GetColor16( 255, 0, 255 );
GetRGB( wSurf2[ y * 256 + x] );
Now it should be, R = 248, G = 0, B = 248. But it's not.
It's R = 248, G = 28, B = 248. Hmmmm. I remove the << 2
and I found that G gets the value 7 when it should be 0.
Pretty much the same thing happened when I wrote (0,255,255)
it read (56,124,248). (124 can be fixed by shifting the G by
3 instead). Any ideas why this happens.

And Reaver, would the Mask and shift be correct in 24 or 32
bpp mode too, using the GetNumberOfBits thingie?

If you are passing 24-bit values (0 to 255), You need to convert them to
16-bit values (0 to 31) before you combine them together. Try this for
your GetColor16() function:

code:
 WORD  GetColor16(BYTE r, BYTE g, BYTE b) {    return (WORD)( (((r>>(8-wRBits))&31) << m_wRShift) | (((g>>(8-wGBits))&31) << m_wGShift) | ((b>>(8-wBBits))&31) ); }


I hope that came out right.

Hmmm, or try this:

code:
 WORD  GetColor16(BYTE r, BYTE g, BYTE b) {    return (WORD)( ((r>>(8-wRBits)) << m_wRShift) | ((g>>(8-wGBits)) << m_wGShift) | (b>>(8-wBBits)) ); }

I don't know if that will do much visually, but I just remembered I put in
the &31 part because I want all color to clamp to 555, even though it might be 565.
Or you could try substituting &63 for the &31 part in the green component.
I never tried this, it might not work right.

If that doesn't work, make sure you have everything setup correctly, write
out your masks values, shift values, and bit count values. Make sure it is
all correct for 16-bit 565.

And, I think you don't need to use GetNumberOfBits or figure out
how bits to shift with 24-bit, because it usually only has one format.
At least I hope so. Always 888 for 24-bit. I think 32-bit can be
2-10-10-10 or 8-8-8-8. I never tested it with anything else than 16-bit,
but I would guess it would still give you the same results.

Reaver

[This message has been edited by Reaver (edited November 01, 1999).]

The thing is though, if you want to make a 16bit engine you have to have RGB color ranges from 0-31. You can't have 0-255.

For 555 format
R = 32 shades
G = 32 shades
B = 32 shades
Total 32768 colors

For 565 format
R = 32 shades
G = 64 shades
B = 32 shades
Total 65536 colors

I dont think that our eyes can even notice all thoses shades.

#define RGB16(r, g, b) ((r << RedPos) | (g << GreenPos) | b)
When you call this macro with 255,255,255 it truncates them down to 31,31,31

So then when you plot lets say a pure red pixel with 255 and you call this macro to extract the red color
#define RED(p)(p >> RedPos)

The value you will get is 31.

So if you make a 16 bit engine you have to stick with 31 shades. Ifnot you will have to go up to 24bit mode or 32 bit mode but those are still to frigin slow.

Hardcore Until The End.
You'd be surprised what the eye can distinguish. It can reliably discern all the 16M colors of 24bit color modes, because all it really does it discern the 256 levels of each RGB. Even more impressive is that it can distinguish about 50M colors on a reflective surface such as paper!

Rock

Hi everybody,

How do I extract each color components of a 16bit 565 color?
I tried this:
B = col & 0x1F;
G = (col >> 5) & 0x3F;
R = (col >> 11) & 0x1F;
But it didn't work very well, color values are just between 0-31, I want them 0-255.
There must be some way, please help.

TIA, Tobias

This topic is closed to new replies.

Advertisement