Direct Draw 32bit setup

Started by
5 comments, last by Aardvajk 17 years, 7 months ago
okay i am having trouble figuring out whats going on with my program. I am trying to get my direct draw 2d tile based game to use 32bit depth so i dont have to worry about using palletes. I read that using this macro:

#define RGB_32BIT(r, g, b) ((r << 16) | (g << 8) | (b))

and then the SetDisplayMode needs to be:

if(lpdd->SetDisplayMode(SCREEN_W, SCREEN_H, SCREEN_BB)!=DD_OK)
   return(0);

Now... I have these both in my application, and it prints the bitmaps in grayscale and the bitmap is displayed in pairs of 4. If this helps, i had it in 8 bit palettized mode before i changed it over to 32. I had the palette set up for it. I think it has something to do with switching over. maybe the loading function isn't calculated to load a source rect to a destination rect for 32 bit files.

// This code blits the bitmap onto a surface the size of the bitmap,
// the surface was created in a call before this one.
UCHAR *source_ptr, *dest_ptr;

//cy and cx are the cells on the bitmaps
source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
ddsd.dwSize = sizeof(ddsd);
(bitmap->surface)->Lock(NULL, &ddsd, DDLOCK_WAIT | 
                        DDLOCK_SURFACEMEMORYPTR, ULL);
dest_ptr = (UCHAR *)ddsd.lpSurface;

for(int index_y = 0; index_y < bitmap_height; index_y++)
{
   memcpy(dest_ptr, source_ptr, bitmap_width);
   dest_ptr   += bitmap_width;
   source_ptr += bitmap->bitmapinfoheader.biWidth;
}
(bitmap->surface)->Unlock(ddsd.lpSurface);

i dont know if the code above needs to be altered because the bit depth is now 32bits.
Advertisement
This is a problem for the DirectX forum... I'll move it.
This code is wrong:
for(int index_y = 0; index_y < bitmap_height; index_y++){   memcpy(dest_ptr, source_ptr, bitmap_width);   dest_ptr   += bitmap_width;   source_ptr += bitmap->bitmapinfoheader.biWidth;}

It should be:
for(int index_y = 0; index_y < bitmap_height; index_y++){   memcpy(dest_ptr, source_ptr, bitmap_width * 4); // 4 bytes per pixel   dest_ptr   += surface_pitch; // Use pitch, not width   source_ptr += bitmap->bitmapinfoheader.biWidth;}

I don't know about DirectDraw (It's been years since I used it), but you need to use the surface pitch when locking surfaces, since the pitch might not be the same as the width. The pitch takes into account the bpp of the surface too.
UCHAR *source_ptr, *dest_ptr;//cy and cx are the cells on the bitmapssource_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;ddsd.dwSize = sizeof(ddsd);(bitmap->surface)->Lock(NULL, &ddsd, DDLOCK_WAIT |                         DDLOCK_SURFACEMEMORYPTR, ULL);dest_ptr = (UCHAR *)ddsd.lpSurface;UINT nPitch = ddsd.lPitch;for(int index_y = 0; index_y < bitmap_height; index_y++){   memcpy(dest_ptr, source_ptr, bitmap_width * 4);   dest_ptr   += nPitch;   source_ptr += bitmap->bitmapinfoheader.biWidth;}(bitmap->surface)->Unlock(ddsd.lpSurface);

Now this shows the two bitmaps where there should be one, and they are in grayscale and strechted vertically. if i use UINT nPitch = ddsd.lPitch >> 2; it shows the old grayscale, and 4 bitmaps where there should be one, it is resizing the bitmaps. I'm going to post my bitmap file loading function to see if thats the problem.
int Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename){  int file_handle, index;  OFSTRUCT  file_data;        // file data information  if(file_handle = OpenFile(filename, &file_data, OF_READ)) == -1)    return(0);  _lread(file_handle, &bitmap->bitmapfileheader, sizeof(BITMAPFILEHEADER));  if(bitmap->bitmapfileheader.bfType != BITMAP_ID)  // #define BITMAP_ID 0x4D42  {     _lclose(file_handle);     return(0);  }    _lread(file_handle, &bitmap->bitmapinfoheader, sizeof(BITMAPINFOHEADER));  if(bitmap->bitmapinfoheader.biBitCount == 8)  {     _lread(file_handle, &bitmap->palette, 256*sizeof(PALETTENTRY));     //Set to RGB instead of BGR.     for(index = 0; index < 256; index++)     {        int temp_color = bitmap->palette[index].peRed;        bitmap->palette[index].peRed = bitmap->palette[index].peBlue;        bitmap->palette[index].peBlue = temp_color;        bitmap->palette[index].peFlags = PC_NOCOLLAPSE;     }  }  _lseek(file_handle, -(int)(bitmap->bitmapinfoheader.biSizeImage), SEEK_END);  if(bitmap->bitmapinfoheader.biBitCount == 8  ||      bitmap->bitmapinfoheader.biBitCount == 16 ||     bitmap->bitmapinfoheader.biBitCount == 24)  {     if(!(bitmap->buffer = (UCHAR *)malloc(bitmap->bitmapinfoheader.bitSizeImage);     {        _lclose(file_handle);        return(0);     }     _lread(file_handle, bitmap->buffer, bitmap->bitmapinfoheader.biSizeImage);  }  return(1);}

I also have a #if 0... then it writes the bitmap info to printf... but i dont see how that could be the problem. any help would be appreciated. thanks.

[Edited by - Nokame on September 7, 2006 7:22:27 PM]
How is that macro 32bit? I don't see an alpha so that's really 24bit.
so whats a 32 bit macro, and if i use 24 bits, is it still gonna be 4bytes per line? the question is......... WHY are my bitmaps all F***ed up? i just can't find any example code on a 32 bit depth or 24 bit depth direct draw setup. what i have written there are just blurps of people saying in their tutorials... "oh... just so you know you can set up the app with 16 bit 24 bit or 32 bits, but i'm going to show you how to do it with a palette in shitty 8 bits" and i can understand why... because directdraw is just about dead, and most of the tutorials written were at least 4 years ago haha. anyways, i still need help
It looks to me, and I apologise if I am wrong, that you are just loading the bitmap data straight from the file in binary format, then attempting to just copy this data as is onto a DirectDraw surface. If that is not the case and I have misread your post, please ignore the below.

I may have some of the details of the below a bit incorrect but the principle is basically sound:

If you load from a 8 bit bitmap, the image data in the file is stored as a sequence of one-byte-per-pixel where each byte is an index into the palette. Equally, if you load a 16-bit image then the image data is a sequence of two-bytes-per-pixel, each containing the r-g-b values. A 24-bit bitmap would represent this as three-bytes-per pixel and so on. Here is some more info about the BMP format.

When you create a 32-bit DirectDraw surface, the data is organised with four bytes per pixel, a red, green, blue and reserved (since DirectDraw doesn't support alpha directly).

Let's say you have a 3x1 bitmap containing green pixels in a 24 bit bitmap. If you read this data in directly, it will look like this as bytes:

0 255 0 0 255 0 0 255 0

The equivalent sized 32bit DirectDraw surface probably would look like this:

0 255 0 0 0 255 0 0 0 255 0 0

although I don't think this is not guaranteed since the pixel format order can vary from hardware to hardware.

Obviously if you just dump the format from the 24bit BMP file into this buffer, the result will not be what you are expecting.

Converting pixel formats is a large and complex issue, especially in DirectDraw, and would require substantial amounts of code to get right.

As I have suggested before, I think the problem is that you are attempting to write your own code to load bitmaps and copy them onto surfaces. The easiest way to load a bitmap onto a DirectDraw surface is to use the Win32 API LoadImage to get a HBITMAP, use CreateCompatibleDC and SelectObject to assign a bitmap to a device context, then use DirectDrawSurface::GetDC to get a device context to the surface. StretchBlt can then take care of copying the bitmap onto the surface and will do any pixel conversions you require via the GDI.

I'm at work at the moment but if you need me to post some code demonstrating this, I'll do so tonight.

This topic is closed to new replies.

Advertisement