Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


16 bit color


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 Ake   Members   -  Reputation: 122

Like
Likes
Like

Posted 02 November 1999 - 04:56 PM

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


Sponsor:

#2 Gromit   Members   -  Reputation: 144

Like
Likes
Like

Posted 01 November 1999 - 05:53 AM

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



#3 Ake   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 07:06 AM

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



#4 Reaver   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 07:27 AM

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).]


#5 Alastair   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 09:36 AM

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!


#6 Ake   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 09:44 AM

Thanks a bunch, guys...


#7 Ake   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 11:01 AM

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?


#8 Reaver   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 12:51 PM

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).]


#9 voodoo   Members   -  Reputation: 122

Like
Likes
Like

Posted 01 November 1999 - 05:50 PM

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.


#10 Rock2000   Members   -  Reputation: 122

Like
Likes
Like

Posted 02 November 1999 - 06:15 AM

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


#11 voodoo   Members   -  Reputation: 122

Like
Likes
Like

Posted 02 November 1999 - 04:56 PM

Anyways, the point is if you are going 16bit you will always come back to 32 shades of each color no matter what you do even if you convert to 255. So if you really want more colors you have no choice but to go 24 or 32bit. But since both modes you need to work in DWORD alignement cause there is not 3 byte
alignement, might as well go full 32bit. But stick to 16 cause it's way faster then 24 and 32 and still looks good

[This message has been edited by voodoo (edited November 02, 1999).]

[This message has been edited by voodoo (edited November 03, 1999).]





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS