Archived

This topic is now archived and is closed to further replies.

Guest Anonymous Poster

Bitmap color depth problem

This topic is 6565 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

Guest Anonymous Poster
Yeah, but even so why is the bitdepth of the bitmap always the screen resolution color depth? as in bmBitBitsPixel is...

Share this post


Link to post
Share on other sites
Isn't this a problem like GetDIBits??? If the bitmap is a specific bitdepth, then you hafta call GetDIBits twice to get the palette, or something like that??? I'm not really sure

------------------
Dance with me......

Share this post


Link to post
Share on other sites
I believe you have to load it like:

hbmp = (HBITMAP)LoadImage(hInst, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

GetObject(hbmp, sizeof(BITMAP), &bm);

ddsd.ddpfPixelFormat.dwRGBBitCount = bm.bmBitsPixel;


Jim Adams

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Ok, now i find that if the surface is 1, 4, or 8 bit depth then i have to do this when declaring the surface:

ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;

but if it's not, i just can use:

ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;

Now if it's not 1, 4, or 8, I also seem to need to define the ddsd.ddpfPixelFormat.dwRBitMask, dwGBitMask, and dwBBitMask.

Currently the bitmap I write is all black, and i think it's because I don't know how to fill out those three values. So how do i do this?

Share this post


Link to post
Share on other sites
Just a guess,but I would think you would have to do something like this:

unsigned char rbits, gbits, bbits;

rbits = dwRBitMask << 16;
gbits = dwGBitMask << 8;
bbits = dwBBitMask ;

Or something along those lines. CJ would probably be the guy to answer it correctly though Hopefully I didn't screw you up too bad.


------------------
Still Learning...

Share this post


Link to post
Share on other sites
um....

i'm not sure what you're trying to do, and i'm not sure why you're trying to do it...

are you using the bit depth of the bitmap for the bitdepth of a pixel format for use in a call to IDirectDrawSurface::SetSurfaceDesc()? or is this for a call to IDirectDraw::CreateSurface()?

neither one really makes any sense, since eventually you'll have a call that makes the surface incompatible with the primary (and why would someone want to do that?)

if your goal is to load a bitmap from a file and have it wind up on a surface, then you need to:

a) load the bitmap (as you are doing)
b) use GetObject to get the stats of the bitmap(as you are doing)
c) use the width and height to create an offscreenplain surface (DONT use the bpp anywhere)
d) create a system DC with CreateCompatibleDC
e) use SelectObject to select the bitmap you loaded into the system DC you just created (be sure to save the return value from SelectObject, as you will be restoring it late)
f) use the GetDC() member function of the new surface you created
g) BitBlt the contents of the system DC onto the new surface
h) use the ReleaseDC() member function of the new surface
i) use SelectObject to restore the old bitmap to the system dc
j) delete the bitmap you loaded
k) delete the system dc

follow these steps, and you wont have to care about the bpp of the bitmap OR the bpp of the primary surface, or the bpp of anything. the call to BitBlt handles all of the conversion for you.

****LET THE PLATFORM DO THE WORK****

Share this post


Link to post
Share on other sites
I don't see what you are trying to do. Writing a bitmap or loading a bitmap.

Your last post looks like you are trying to write one. A BMP file I suppose....

Ok, one post of yours implies about 1, 4 and 8 bit. They are all paletized so what you are trying to do is right. But...when you want to either write 16, 24 or 32 bit to a bitmap file. You need to store all the values. Most of them stored as BGR or ABGR (you can leave the A unchecked, it's for transparency use).
To write you use an unsigned char, since each of them can contain a value from between 0 and 255.
Also remember to fill in all the parameters necessary in the BITMAPFILEHEADER and BITMAPINFOHEADER. If you write your own file format. Remember to take into account what you need to store and do with it.

I would suspect that you want to write something to make a screenshot. Since it is all stored on a DirectDraw Surface,......you lock the surface, and get a pointer to the lpSurface (pointer should be an unsigned char for both 32 and 24 bit surfaces). if it is a 16 bit surface..you'd better get a word. In THIS case you need to know what the video card uses, hence the ddsd.ddpfPixelFormat.dwRBitMask and the other values. try to get the real values out of it. (don't want to think too much now, but I believe it was like ((r << 3) >> 10, (g << 3) >> 5, b << 3) for a 1555. And ((r << 3) >> 11, (g << 2) >> 5, b << 3) for a 565...but I may well be wrong, it's out of my head.....note that this won't give you the real rgb values....but values like 31 or something.....I don't work with 16 bit anymore, so.......
You might want to take a look at
http://members.xoom.com/CJdeVos/index.htm

from there there is an article I wrote called 32, 24, 16 and 8 bit

I'm tired now, i probably forgot a lot but oh well.....


------------------
Dance with me......

Share this post


Link to post
Share on other sites
Hmmmm, after I checked this site again and answered, I thought about implementing a screenshot option. So.....if you are interested, here's a part of the source code I just implemented. (NOTE, 24 bit surfaces only..easily changed to 32 bit though).

code:
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

void WriteBitmap()
{
unsigned char *Buffer;
int Pitch;
Buffer = LockSurface(backsurf, &Pitch);

char B = 'B'; // BM = 0x4d42
char M = 'M';

short Reserved1 = 0;
short Reserved2 = 0;
long PixelOff = 54;
long Compression = 0;
long Cmpsize = 0;
long colors = 0;
long impcol = 0;

DWORD widthDW = WIDTHBYTES(modewidth * 24);

long BitmapFileSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + widthDW * modeheight;
long Written = 0;

BITMAPINFOHEADER header;
header.biSize = 40; // header size
header.biWidth = modewidth;
header.biHeight = modeheight;
header.biPlanes = 1;
header.biBitCount = modedepth; // RGB encoded, 24 bit
header.biCompression = BI_RGB; // no compression
header.biSizeImage = 0;
header.biXPelsPerMeter = 0;
header.biYPelsPerMeter = 0;
header.biClrUsed = 0;
header.biClrImportant = 0;

FILE *fp;
fp=fopen("temp.bmp","wb");
if (fp==NULL)
{
//Can't open file for writing;
return;
}

// should probably check for write errors here...

fwrite((BYTE *)&(B), 1, 1, fp); Written += 1;
fwrite((BYTE *)&(M), 1, 1, fp); Written += 1;
fwrite((long *)&(BitmapFileSize), 4, 1,fp); Written += 4;
fwrite((int *)&(Reserved1), 2, 1, fp); Written += 2;
fwrite((int *)&(Reserved2), 2, 1, fp); Written += 2;
fwrite((long *)&(PixelOff), 4, 1, fp); Written += 4;

fwrite((BITMAPINFOHEADER *)&header, sizeof(BITMAPINFOHEADER),1,fp);
Written += sizeof(BITMAPINFOHEADER);

long row = 0;
long RowIndex;
long row_size;
row_size = header.biWidth * 3;
long ReadCount;
for (row = header.biHeight-1; row >= 0; row--)
{
RowIndex = (long unsigned)row * row_size;

// write a row
ReadCount = fwrite((void *)(Buffer + RowIndex), row_size, 1, fp);
if (ReadCount != 1)
{
//fwrite error....Giving up;
break;
}
Written += row_size;

// pad to DWORD...so that the image won't look 'weird' ie. like /
for (DWORD count = row_size; count < widthDW; count++)
{
char Nothing = 0;
fwrite(&Nothing, 1, 1, fp);
Written++;
}
}
fclose(fp);
UnlockSurface(backsurf);
}


There is, however, a small problem I encountered after writing this down, and checking. And that is that.......some parts of the lines I displayed on the screen didn't appear on the bitmap.

I'll look for the solution though.

Also an article about writing bitmaps will appear on my site soon, as I found quite a lot of questions about it.

------------------
Dance with me......

Share this post


Link to post
Share on other sites
No wonder....i forgot the pitch

change that one line into

RowIndex = (long unsigned)row * Pitch;

------------------
Dance with me......

http://members.xoom.com/CJdeVos/index.htm

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Thank you all for your help. To tell you the truth, I had to figure it all out on my own. But I do appreciate all the effort oyu guys put into trying to help me.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I do the following to load a bitmap and set a ddraw surface to it's bit depth.

hbmp = (HBITMAP)LoadImage(hInst, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbmp, sizeof(BITMAP), &bm);
ddsd.ddpfPixelFormat.dwRGBBitCount = bm.bmBitsPixel;

The bitmap I am loading is 8 bit, but the surface is always set to the depth of the screen resolution. i checked, and bm.bmBitsPixel is this value too. What do i need to do to get the proper bit depth of the bitmap?

Share this post


Link to post
Share on other sites