Recent Resources
-
GLSL 4.0: Discarding Fragments to Create a Perf...
-
GLSL 4.0: Using Subroutines to Select Shader Fu...
-
Building a Complete Board-based Puzzle Game wit...
-
JIRA: Programming Workflows
-
.NET Generics 4.0: Container Patterns and Best...
-
Raw Meat: Game Design Tips from Team Meat's...
-
Sedge: An Automated Error Reporting Tool
16-bit Color
By TANSTAAFL | Published Nov 23 1999 03:29 PM in DirectX and XNA
Today, I'm going to address a problem that you might be dealing with, or dealing with in the near future… rectifying a 24-bit image onto a 16-bit DirectDraw surface.
A few days ago, I was working on my old computer, an ATI VGA Wonder. It had 5 bits for each R,G, or B value(using only 15 bits), so the pixel format looked something like this
XRRRRRGGGGGBBBBB
Now, my new computer has a better video card. It uses all 16 bits, making the pixel format look like:
RRRRRGGGGGGBBBBB
So, I got to thinking… how am I going to make it so that I can specify any color to put on the screen, and have it turn out right, no matter what video card it is.
As a side note, I have written my own bitmap loader to read in 24 bit BMPs, and rectify them to a 16 bit surface (I'll probably share it at some later time, most likely in a separate article)
I sat down and set about my task. The first thing I did was open up the DirectX.hlp file, and took a look at the IDirectDrawSurface Interface. One of its member functions was called "GetPixelFormat". Okay. I had something to work with.
GetPixelFormat takes a pointer to a DDPIXELFORMAT structure (not surprisingly). I looked at the DDPIXELFORMAT structure, and I found a couple of fields that interested me… namely dwRBitMask, dwGBitMask, dwBBitMask.
Now I had all of the information I wanted, just not in a format I could use.
Well, in order to figure out how far to shift bits to the left, I had to do this:
So, let's determine how many bits to the right we have to shift them:
Now, we can accurately calculate a 16bit color from a 24Bit color.
A few days ago, I was working on my old computer, an ATI VGA Wonder. It had 5 bits for each R,G, or B value(using only 15 bits), so the pixel format looked something like this
XRRRRRGGGGGBBBBB
Now, my new computer has a better video card. It uses all 16 bits, making the pixel format look like:
RRRRRGGGGGGBBBBB
So, I got to thinking… how am I going to make it so that I can specify any color to put on the screen, and have it turn out right, no matter what video card it is.
As a side note, I have written my own bitmap loader to read in 24 bit BMPs, and rectify them to a 16 bit surface (I'll probably share it at some later time, most likely in a separate article)
I sat down and set about my task. The first thing I did was open up the DirectX.hlp file, and took a look at the IDirectDrawSurface Interface. One of its member functions was called "GetPixelFormat". Okay. I had something to work with.
GetPixelFormat takes a pointer to a DDPIXELFORMAT structure (not surprisingly). I looked at the DDPIXELFORMAT structure, and I found a couple of fields that interested me… namely dwRBitMask, dwGBitMask, dwBBitMask.
Now I had all of the information I wanted, just not in a format I could use.
DDPIXELFORMAT ddpf;What now?
memset(&ddpf,0,sizeof(DDPIXELFORMAT);
ddpf.dwSize=sizeof(DDPIXELFORMAT);
lpDDS->GetPixelFormat(&ddpf);
Well, in order to figure out how far to shift bits to the left, I had to do this:
//warning, this code is UGLYAt this point, if we assumed that I had the correct number of bits stored in three UCHARs named Red, Green, and Blue, I could calculate the 16-bit color by doing this:
DWORD dwBMask=ddpf.dwBBitMask;
DWORD dwRMask=ddpf.dwRBitMask;
DWORD dwGMask=ddpf.dwGBitMask;
DWORD dwBSHL=0;
DWORD dwRSHL=0;
DWORD dwGSHL=0;
while((dwBMask & 1)==0)
{
dwBMask=dwBMask >> 1;
dwBSHL++;
}
while((dwGMask & 1)==0)
{
dwGMask=dwGMask >> 1;
dwGSHL++;
}
while((dwRMask & 1)==0)
{
dwRMask=dwRMask >> 1;
dwRSHL++;
}
Color=Blue << dwBSHL + Green << dwGSHL + Red << dwRSHL;However, right now, we have 8 bits in each of Red, Green, and Blue, and we need only 5 or 6. We have to be able to shift the bits of the colors to the right before shifting them to the left to make a 16-bit color.
So, let's determine how many bits to the right we have to shift them:
DWORD dwBSHR=8;
DWORD dwRSHR=8;
DWORD dwGSHR=8;
while((dwBMask & 1)==1)
{
dwBMask=dwBMask >> 1;
dwBSHR--;
}
while((dwGMask & 1)==1)
{
dwGMask=dwGMask >> 1;
dwGSHR--;
}
while((dwRMask & 1)==1)
{
dwRMask=dwRMask >> 1;
dwRSHR--;
}
Now, we can accurately calculate a 16bit color from a 24Bit color.
Color=(Blue >> dwBSHR) << dwBSHL + (Green >> dwGSHR) << dwGSHL + (Red >> dwRSHR) << dwRSHL;


















