Archived

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

hibiki_konzaki

loading bitmaps with DDraw

Recommended Posts

I need to know how to load bitmaps onto a DirectDraw7 surface. I''ve tried Google, the forums search, and everywhere newbs get roasted for because they didn''t look, but nothing has worked. I tried DDLoadBitmap(), but that didn''t work. I''ve tried that function in one of the GameDev tutorials, and that didn''t work (it came up with 102 errors then stopped because it went over 100). So if someone could suggest a site or show me a function that would help out, I''d be really happy. Thanks. Hibiki Wheres the any key?

find your element at mutedfaith.com. <º>

Share this post


Link to post
Share on other sites
I don't know if it's the only way, but the way I load bitmaps onto DirectDraw surfaces is to load them into a GDI DC, obtain a DC for the surface and then BitBlt.

Something along the lines of:-


  
HDC hdc, hdcMem;
hdc = GetDC(hwnd);
hdcMem = CreateCompatibleDC(hdc);
ReleaseDC(hwnd, hdc);

HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "filename.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);

SelectObject(hdcMem, hBitmap);

BITMAP bitmap;
GetObject(hBitmap, sizeof(BITMAP), &bitmap);

lpddSurface->GetDC(&hdc);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
lpddSurface->ReleaseDC(hdc);


Remember to delete your objects afterwards, i.e. DeleteObject(hBitmap) etc.

Also, when you create the surface you need to specify the width and height in the DDSURFACEDESC2 structure. You can get these from bitmap.bmWidth and bitmap.bmHeight.

All of the functions are in the MSDN so if you don't understand any of it, have a look.

Hope this helps.

PhilHalf

[edited by - PhilHalf on July 30, 2002 4:12:56 AM]

Share this post


Link to post
Share on other sites
Hello...
When i first statred with directx, I spent the most time trying to get the damn bitmap loaded and on a surface, just to see if I could get it on the screen. After all my work, I discovered the little code snippet from microsoft. It might not be the best way, but it should work. Somewhere in all thoes Directx examples, is a file called ddutil.cpp
Here''s an enample of some of the code in that file...

//-----------------------------------------------------------------------------
// Name: DDLoadBitmap()
// Desc: Create a DirectDrawSurface from a bitmap resource.
//-----------------------------------------------------------------------------
extern "C" IDirectDrawSurface7*
DDLoadBitmap( IDirectDraw7* pdd, LPCSTR szBitmap, int dx, int dy)
{
HBITMAP hbm;
BITMAP bm;
DDSURFACEDESC2 ddsd;
IDirectDrawSurface7 *pdds;

//
// Try to load the bitmap as a resource, if that fails, try it as a file
//
hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx,
dy, LR_CREATEDIBSECTION);
if (hbm == NULL)
hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (hbm == NULL)
return NULL;
//
// Get size of the bitmap
//
GetObject(hbm, sizeof(bm), &bm);
//
// Create a DirectDrawSurface for this bitmap
//
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = bm.bmWidth;
ddsd.dwHeight = bm.bmHeight;
if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
return NULL;
DDCopyBitmap(pdds, hbm, 0, 0, 0, 0);
DeleteObject(hbm);
return pdds;
}

I justed used this last night, and there were no problems. Make sure you''re using LPDIRECTDRAWSURFACE7, or change that part to the version you are using.
Ciao... hope this helps

I think, therfore I am.
I think?

Share this post


Link to post
Share on other sites
Using the DDLoadBitmap, I got this error:

c:\program files\microsoft visual studio\myprojects\engine\engine.cpp(59) : error C2065: ''DDCopyBitmap'' : undeclared identifier

I included ddutil and dxutil.h/cpp from the DX8 SDK and everything is linked right. I haven''t tried to call the function yet, I just put it in my test program and tried to compile it.

Also, in my ddutil.h/cpp everything is based off a class (which I also read a tutorial about, but when I try to run the program it closes before anything happens, which is what happened when I tried the CDX lib).

Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>

Share this post


Link to post
Share on other sites
The DDCopyBitmap is another fn() in the ddutil.cpp folder
Here is the stuff I use. Don't forget to add the error checking stuff, so if it doesn't work, you'll at least know what isn't woking.



    
/////////////////////////////////////////////////

// load_bitmap_file()

/////////////////////////////////////////////////

void CDirectDraw::load_bitmap_file(LPDIRECTDRAWSURFACE7& lpdds, FILE file)
{
HBITMAP hbm = NULL; // Handle to bitmap for LoadImage()

BITMAP bm; // Bitmap struct



//...Try to load the bitmap as a resource, if that fails, try it as a file


hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL),
file,
IMAGE_BITMAP,
NULL,
NULL,
LR_CREATEDIBSECTION);
if (hbm == NULL){
hbm = (HBITMAP) LoadImage(NULL, // handle of instance

file, // file name

IMAGE_BITMAP, //IMAGE_BITMAP NULL, // Witdth of bitmap

NULL, // Height of bitmap LR_LOADFROMFILE | LR_CREATEDIBSECTION

}//end if


if ( hbm == NULL ){
ThrowEx(__LINE__,__FILE__);
}//end if


//...put Bitmap info into bm struct


if( GetObject( hbm, sizeof(bm), &bm ) == NULL ){
DeleteObject(hbm); // From GetObject call up there

ThrowEx(__LINE__,__FILE__);
}

//...create a DirectDrawSurface for this bitmap


create_offscreen_surface(lpdds, bm.bmWidth,bm.bmHeight);//user defined fn()


//...Put the bitmap we loaded on the new surface


copy_bitmap( lpdds, hbm, bm.bmWidth, bm.bmHeight );// user defined fn()


DeleteObject(hbm); // From GetObject call up there


}
/////////////////////////////////////////////////

// create_offscreen_surface()

/////////////////////////////////////////////////

void CDirectDraw::create_offscreen_surface(
LPDIRECTDRAWSURFACE7 &NewSurface,
DWORD width,
DWORD height )
{

//...Clear memory and set flags

clear(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = width;
ddsd.dwHeight = height;

if( FAILED( lpdd->CreateSurface(&ddsd, &NewSurface, NULL))){

safe_delete(NewSurface);

ThrowEx(__LINE__,__FILE__);

}// end if


}
/////////////////////////////////////////////////

// copy_bitmap()

/////////////////////////////////////////////////

void CDirectDraw::copy_bitmap(
LPDIRECTDRAWSURFACE7 &lpddsToCopy,// Surface to copy too

HBITMAP hbm, // handle to bitmap to copy

DWORD width,
DWORD height )
{
HDC hdcImage = NULL; // use in StretchBlt()

HDC hlpddsToCopy = NULL; // use in StretchBlt()


if( hbm == NULL || lpddsToCopy == NULL )
ThrowEx(__LINE__,__FILE__);

//...select bitmap into a memoryDC so we can use it


hdcImage = CreateCompatibleDC( NULL ); // so we can put handle into this with SelectObject


if( hdcImage == NULL )
ThrowEx(__LINE__,__FILE__);

SelectObject( hdcImage, hbm ); // puts bitmap handle into this


if( FAILED( lpddsToCopy->GetDC( &hlpddsToCopy ))) // Get DC handle for Surface to Blt too

ThrowEx(__LINE__,__FILE__);

// Put Bitmap on surface ////////////////////////


if( FAILED( StretchBlt(
hlpddsToCopy, // handle of destination surface

0, 0, // (x,y) of destination rect

width, // Width of destination surface

height,// Height of destination surface

hdcImage, // handle of source surface

0, 0, // (x,y) of source surface

width, // Width of source

height, // Height of source

SRCCOPY )))
{
ThrowEx(__LINE__,__FILE__);

}// end if


lpddsToCopy->ReleaseDC(hlpddsToCopy); // To clean up GetDC(&hlpddsToCopy)



DeleteDC(hdcImage);// To clean up memory device context

// hdcImage = CreateCompatibleDC(NULL)


}//end copy_bitmap()




Hope this helps...

I think, therfore I am.
I think?

[edited by - glass_knife on July 30, 2002 4:49:52 PM]

Share this post


Link to post
Share on other sites
Ok, I've got it to work and the error detection comes up ok, but when it shows the bitmap, it shows random windows icons like the recycle bin and other stuff like that then after about 2 seconds of that, random lines start coming up, and it's all within the bounds of where I want to blit it to.

Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>


[edited by - hibiki_konzaki on July 30, 2002 7:56:31 PM]

Share this post


Link to post
Share on other sites
Well, I''m using the first function you gave me and copy_bitmap, and heres my game_main function (it''s not comlpete,I''m just trying to get something to the screen before I start on the game):

Clear_Screen(lpddsback,RGB565(0,0,0));

RECT somerect = {200,200,246,298};

if(!(lpddstest = DDLoadBitmap(lpdd,MAKEINTRESOURCEDB_BITMAP1),46,97)) != NULL)
MessageBox(main_window_handle,"error","load bitmap",NULL);

if(FAILED(lpddsback->
Blt(&somerect,lpddstest,NULL,DDBLT_WAIT,NULL)))
MessageBox(main_window_handle,"error","blit",NULL);

if(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT)))
return(0);

Besides that theres around 450 or more lines of your functions, initialization, and windows stuff, and all that is like basic. The function that I use to create off screen surfaces is the one from TOTWGPG, exept I modified it for DX7.

Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>

Share this post


Link to post
Share on other sites
If you do not correctly make an offscreen surface, or the bitmaps are not loaded correctly, the game will crash. So if everything is still running, then there is a problem with what bitmap you are loading (post code), or how you game loop is set up. If my stuff isn''t set up right, it crashes, but if it works, it always loads the bitmap I want, not windows icons.

I think, therfore I am.
I think?

Share this post


Link to post
Share on other sites
It starts up and runs until escape is pressed like it should. The bitmap is ok because it loaded with my other program that uses the ddutil.cpp/h class. Here is my surface creation function, I don't think theres anything wrong with it.


  
LPDIRECTDRAWSURFACE7 DDraw_Create_Surface(int width, int height,
int mem_flags)
{
DDSURFACEDESC2 ddsd;
LPDIRECTDRAWSURFACE7 lpdds;

DDRAW_INIT_STRUCT(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

ddsd.dwWidth = width;
ddsd.dwHeight = height;

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | mem_flags;

if(FAILED(lpdd->CreateSurface(&ddsd,&lpdds,NULL)))
return (NULL);

DDCOLORKEY color_key;
color_key.dwColorSpaceLowValue = 0;
color_key.dwColorSpaceHighValue = 0;

lpdds->SetColorKey(DDCKEY_SRCBLT, &color_key);

return(lpdds);
}


I call this then I call the bitmap loading function in my startup code.

And here is the bitmap loading stuff.


  
IDirectDrawSurface7* DDLoadBitmap( IDirectDraw7* pdd, LPCSTR szBitmap, int dx, int dy)
{
HBITMAP hbm;
BITMAP bm;
DDSURFACEDESC2 ddsd;
IDirectDrawSurface7 *pdds;

//

// Try to load the bitmap as a resource, if that fails, try it as a file

//

hbm = (HBITMAP) LoadImage(GetModuleHandle(NULL), szBitmap, IMAGE_BITMAP, dx,
dy, LR_CREATEDIBSECTION);
if (hbm == NULL)
hbm = (HBITMAP) LoadImage(NULL, szBitmap, IMAGE_BITMAP, dx, dy,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (hbm == NULL)
return NULL;
//

// Get size of the bitmap

//

GetObject(hbm, sizeof(bm), &bm);
//

// Create a DirectDrawSurface for this bitmap

//

ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = bm.bmWidth;
ddsd.dwHeight = bm.bmHeight;
if (pdd->CreateSurface(&ddsd, &pdds, NULL) != DD_OK)
return NULL;
DDCopyBitmap(pdds, hbm, 0, 0);
DeleteObject(hbm);
return pdds;
}

void DDCopyBitmap(LPDIRECTDRAWSURFACE7 &lpddsToCopy, // Surface to copy too

HBITMAP hbm, // handle to bitmap to copy

DWORD width,
DWORD height)
{
HDC hdcImage = NULL; // use in StretchBlt()

HDC hlpddsToCopy = NULL; // use in StretchBlt()

//if( hbm == NULL || lpddsToCopy == NULL )

// ThrowEx(__LINE__,__FILE__);

hdcImage = CreateCompatibleDC( NULL );
//if( hdcImage == NULL )

// ThrowEx(__LINE__,__FILE__);

SelectObject( hdcImage, hbm ); // puts bitmap handle into this // Compatible DC for use in StretchBlt

if( FAILED( lpddsToCopy->GetDC( &hlpddsToCopy ))) // Get DC handle for Surface to Blt too

// ThrowEx(__LINE__,__FILE__);

MessageBox(main_window_handle,"error","error",NULL);
if( FAILED( StretchBlt(hlpddsToCopy, // handle of destination surface

0, 0, // (x,y) of destination rect

width, // Width of destination surface

height, // Height of destination surface

hdcImage, // handle of source surface

0, 0, // (x,y) of source surface

width, // Width of source

height, // Height of source

SRCCOPY )))
{ // SRCCOPY: Copies the source rectangle directly

// to the destination rectangle

// ThrowEx(__LINE__,__FILE__);

}// end if

lpddsToCopy->ReleaseDC(hlpddsToCopy); // To clean up GetDC(&hlpddsToCopy)

DeleteDC(hdcImage);// To clean up memory device context

// hdcImage = CreateCompatibleDC(NULL)

}


Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>


[edited by - Hibiki_Konzaki on July 31, 2002 9:12:54 AM]

Share this post


Link to post
Share on other sites
Thanks for posting the code, it really helps...


this is how you called the function:
if(!(lpddstest = DDLoadBitmap(lpdd,MAKEINTRESOURCEDB_BITMAP1),46,97)) != NULL)

Here is the prtotype:
IDirectDrawSurface7* DDLoadBitmap( IDirectDraw7* pdd, LPCSTR szBitmap, int dx, int dy)

what is MAKEINTRESOURCEDB_BITMAP1?
a define, and if so, what is it?

try
lpddstest = DDLoadBitmap(&lpdd, "bitmap.bmp",46,97);
if(FAILED(lpddstest))
error;

there are extra ()'s in the call, and they way you're checking for a null hurts my head

if this isn't it, let me know. We'll get it.

I think, therfore I am.
I think?

[edited by - glass_knife on July 31, 2002 4:15:28 PM]

Share this post


Link to post
Share on other sites
Ok, I was using MAKEINT.... to try to load the bitmap as a resource. IDB_BITMAP1 is the bitmap''s define.

Ok, I change the MAKEINT... stuff to the string, and it still does the same thing. Maybe I''m doing something wrong with the blitter..


  
int Game_Main(void *parms = NULL, int num_parms = 0)
{
Clear_Screen(lpddsback,RGB565(0,0,0));

RECT somerect = {1,1,47,98};

if(FAILED(lpddsback->Blt(&somerect,lpddstest,NULL,DDBLT_WAIT,NULL)))
MessageBox(main_window_handle,"error","blit",NULL);

if(FAILED(lpddsprimary->Flip(NULL,DDFLIP_WAIT)))
return(0);

return(1);
}

int Game_Init(void *parms = NULL, int num_parms = 0)
{
ShowCursor(false);

if (FAILED(DirectDrawCreateEx(NULL, (LPVOID*)&lpdd,
IID_IDirectDraw7, NULL)))
return(0);

if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_EXCLUSIVE |
DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT)))
return(0);

if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH,SCREEN_HEIGHT,SCREEN_BPP,
0,0)))
return(0);

ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);

ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP |
DDSCAPS_COMPLEX;

ddsd.dwBackBufferCount = 1;

if (FAILED(lpdd->CreateSurface(&ddsd,&lpddsprimary, NULL)))
return(0);

ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps,&lpddsback)))
return(0);

if (!(lpddstest = DDraw_Create_Surface(46,97,DDSCAPS_VIDEOMEMORY)))
MessageBox(main_window_handle,"error","create surface",NULL);

if(FAILED(DirectInput8Create(hinstance_app,DIRECTINPUT_VERSION,IID_IDirectInput8W, (void**)&lpdi,NULL)))
return(0);

if(FAILED(lpdi->CreateDevice(GUID_SysKeyboard,&lpdikeyboard,NULL)))
return(0);

if(FAILED(lpdikeyboard->SetDataFormat(&c_dfDIKeyboard)))
return(0);

if(FAILED(lpdikeyboard->SetCooperativeLevel(main_window_handle,
DISCL_NONEXCLUSIVE | DISCL_BACKGROUND)))
return(0);

if(FAILED(lpdikeyboard->Acquire()))
return(0);

if(FAILED(lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&list)))
return(0);

lpddstest = DDLoadBitmap(lpdd,"NiggaLeft(1).bmp",46,97);

if(FAILED(lpddstest))
MessageBox(main_window_handle,"error","load bitmap",NULL);

return(1);
}


Clear_Screen() is just a function I made that fills the given surface with the given color.

Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>

Share this post


Link to post
Share on other sites
I see a mistake, and it's my fault...
If the load bitmap worked it returns DD_OK.
When I tried this:
lpddsBase = dd->load_bitmap_file("playingarea002.bmp");
if(FAILED(lpddsBase))
{
ERROR
}

I got the error, because Failed returns true if it's not DD_OK.
And lpddsBase is != DD_OK

I changed it to (if lpddsBase == NULL), and it loaded just
fine.

This just in...I just recreated your bug!!! My bitmaps looked all funky, and I know why.

Also, in your DDLoadBitmap, you are doing this:
DDCopyBitmap(pdds, hbm, 0, 0);
The 0,0 are the width and hight of the source and destination.
They cannot be 0; This is what caused it.

solution 1:
take out the stretchblt, and put in a blt instead;

solution 2:
call the fn() like this
DDCopyBitmap(pdds, hbm, bm.bmWidth, bm.bmHeight);

Let me know...


I think, therfore I am.
I think?

[edited by - glass_knife on July 31, 2002 6:17:40 PM]

Share this post


Link to post
Share on other sites
I''ve been using C++ for about a year now, I''ve made a partially completed text RPG, some stuff for TI-83 claculators (in both TI83 BASIC and Z80 Assembly) and a pong game in VC++ and DX just using filled squares and stuff. Right now I''m working on a 2-d side scrolling shooter. Basically you go around different levels and shoot people. Not really much of a story, but I''m also not a pro dev team with a million dollar budget

Hibiki
Wheres the any key?





find your element
at mutedfaith.com.
<º>

Share this post


Link to post
Share on other sites