Sign in to follow this  

Need help load .bmp files

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

Hi, I am trying to load a BMP into an offscreen, DirectDraw7 surface. This is the code i'm using functions:
///Create Surface///////////////////////////////////////////////////////////
//Creats any size surface
//////////////////////////////////////////////////////////////////////////
void MercuryEngine::CreateSurface(LPDIRECTDRAWSURFACE7 *lpSource, int xs, int ys)
{
   DDSURFACEDESC2 ddsd;

   ZeroMemory(&ddsd, sizeof(ddsd));
   ddsd.dwSize = sizeof(ddsd);
   ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT;
   ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
   ddsd.dwWidth = xs;
   ddsd.dwHeight = ys;
   ddsd.ddckCKSrcBlt.dwColorSpaceLowValue = _RGB32BIT(0,0,32,0);
   ddsd.ddckCKSrcBlt.dwColorSpaceHighValue = _RGB32BIT(0,0,32,0);
   lpdd->CreateSurface(&ddsd, lpSource, NULL);
}


/////DrawHBitmap/////////////////////////////////////////////////////
// Blts a bitmap to surface
////////////////////////////////////////////////////////////////////////////
void MercuryEngine::DrawHBitmap(IDirectDrawSurface7 *lpSurface, HBITMAP hBitmap, int x, int y, int width, int height)
{
   HDC           hdcImage;
   HDC           hdc;
   BITMAP        bm;

   if (lpSurface == NULL || hBitmap == NULL)
      return;
   lpSurface->Restore();

   hdcImage = CreateCompatibleDC(NULL);
   SelectObject(hdcImage, hBitmap);

   GetObject(hBitmap, sizeof(bm), &bm);
   width = width == 0 ? bm.bmWidth  : width;
   height = height == 0 ? bm.bmHeight : height;

   lpSurface->GetDC(&hdc);
   BitBlt(hdc, x, y, width, height, hdcImage, 0, 0, SRCCOPY);
   lpSurface->ReleaseDC(hdc);
   DeleteDC(hdcImage);
}

////BitMap load//////////////////////////////////
// Creats a bitmap surface
//////////////////////////////////////////////////
void MercuryEngine::CreateBitmapSurface(LPDIRECTDRAWSURFACE7 lpSurface, char *fname, int xs, int ys)
{
   HBITMAP hBitmap;
   
   this->CreateSurface(&lpSurface, xs, ys);
   
   hBitmap = LoadImage(NULL, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
   this->DrawHBitmap(lpSurface, hBitmap, 0, 0, xs, ys);
   DeleteObject(hBitmap);
}


LPDIRECTDRAW7 lpdd;  //version 7.0 main
DDSURFACEDESC2 ddsd; //primary surface descriptor
LPDIRECTDRAWSURFACE7 DDprimary; //DX primary surface
LPDIRECTDRAWSURFACE7 DDback; //DX BACK surface
LPDIRECTDRAWSURFACE7 DDback_sprite; //DX BACK surface
DDBLTFX ddbltfx; //blt effect
RECT dest_rect; //dest rectangle
RECT src_rect; //source rectangle
RECT clipper_rect[1] = {0,0,799,599}; //fullscrenn clipping area

LPDIRECTDRAWCLIPPER DDclipper; //DD clipper

MercuryEngine GameEngine; //Main Game engine
...
...
...
...
creat our stuff:
// create IDirectDraw interface 7.0 object and test for error
        if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
                Application->MessageBoxA("Error: Can't initialize DirectDraw 7","Error",MB_OK);

        // set cooperation to fullscreen
        lpdd->SetCooperativeLevel(Handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);

        //set display mode
        // 800x600x8bit color
        lpdd->SetDisplayMode(800,600,32,0,0);

        //M$ says clean out our struct
        memset(&ddsd,0, sizeof(ddsd));

        //tell DirectX the size of ddsd
        ddsd.dwSize = sizeof(ddsd);

        //tell DX what valid data we will be giving it
        ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;

        //backbuffer count
        ddsd.dwBackBufferCount = 1;

        //complex , flipable
        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;

        //now create the primary surface
        if(FAILED(lpdd->CreateSurface(&ddsd,&DDprimary,NULL)))
                Application->MessageBoxA("Error: Can't creat primary surface","Error", MB_OK);

        ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

        //atach backbuffer
        if(FAILED(DDprimary->GetAttachedSurface(&ddsd.ddsCaps, &DDback)));

        //creat clipper
        DDclipper = GameEngine.DDCrClipper(DDback,1,clipper_rect);


        //set rect properties
        dest_rect.left   = 0;
        dest_rect.top    = 0;
        dest_rect.right  = 799;
        dest_rect.bottom = 599;
        
        //set rect properties
        src_rect.left   = 0;
        src_rect.top    = 0;
        src_rect.right  = 799;
        src_rect.bottom = 599;

then blt:
//clean us out..
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);

//lock the surface
DDback->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);


DDBLTFX ddbltfx;


 //clean us out..
memset(&ddbltfx,0,sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);


 //set the dwFillColor to desired color
 ddbltfx.dwFillColor = clBlack;

 //ready to blt to surface
DDback->Blt(NULL,       //ptr to des rect
                  NULL,       //ptr to src surface
                  NULL,       //ptr to src rect
                  DDBLT_COLORFILL | DDBLT_WAIT,   //fill and wait
                  &ddbltfx);  //ptr to DDBLTFX structure

DDback->Blt(&dest_rect,DDback_sprite,&src_rect,DDBLT_WAIT, NULL);



//unlock the surface
DDback->Unlock(NULL);

All i get is a flickery screen. No lvl2.bmp showing! I've posted this before, but all I got was "use D3D". Well i don't want to use it for certain reasons. So, in directdraw, what am I doing wrong? Thanks Sigma [Edited by - Coder on October 10, 2004 10:57:06 PM]

Share this post


Link to post
Share on other sites
Yeah, it seems noone here cares about DirectDraw. I never manage to get an answer to DirectDraw questions here so i just have to work things out myself or search the 'net really hard to find the information i need.

Luckily for you though i think i might know whats wrong :)

I don't think Blt operations work with locked surfaces, basically you lock a surface so that you can access the surface memory and put something in it (for example to load an image or to plot pixels on the surface or whatever). So try removing the calls to Lock() and Unlock() before and after the blt and let me know how it goes :)

Share this post


Link to post
Share on other sites
Quote:
Original post by DarkEvilOne
Yeah, it seems noone here cares about DirectDraw. I never manage to get an answer to DirectDraw questions here so i just have to work things out myself or search the 'net really hard to find the information i need.

Luckily for you though i think i might know whats wrong :)

I don't think Blt operations work with locked surfaces, basically you lock a surface so that you can access the surface memory and put something in it (for example to load an image or to plot pixels on the surface or whatever). So try removing the calls to Lock() and Unlock() before and after the blt and let me know how it goes :)


Well, I got rid of the lock/unlock around
DDBLTFX ddbltfx;


//clean us out..
memset(&ddbltfx,0,sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);


//set the dwFillColor to desired color
ddbltfx.dwFillColor = clBlack;

//ready to blt to surface
DDback->Blt(NULL, //ptr to des rect
NULL, //ptr to src surface
NULL, //ptr to src rect
DDBLT_COLORFILL | DDBLT_WAIT, //fill and wait
&ddbltfx); //ptr to DDBLTFX structure

DDback->Blt(&dest_rect,DDback_sprite,&src_rect,DDBLT_WAIT, NULL);


and now my color fill works, but still no bitmap!

Share this post


Link to post
Share on other sites
I don't have much time right now, i'm about to leave for college so i'll take a better look at your code later.

For now could you try loading the bitmap using the functions found in ddutil.h? If that makes it work then theres a problem with your bitmap loading code (sometimes it can be really hard to notice tiny differences in pieces of code that will stop things working). If it still doesn't work then it is more likely to be a problem with your drawing code.

One other thing that you could try, in your blitting code you pass &src_rect to the Blt function but the only place i see src_rect setup is in the DirectDraw initialization code where you set it to the screen dimensions. I'm not sure but DirectDraw might not like it if the source blit rectangle is bigger than the source surface or the destination blit rectangle is bigger than the source rectangle. Again i'm not 100% sure of this but it might be worth checking out :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Telastyn
Indeed. Replacing a half dozen lengthy loading functions with D3DXCreateTextureFromFile() is bound to decrease even the most stalwart DDraw fans.


LOL! You just got told.

Seriously though, stop doing DirectDraw IMMEDIATELY. Now start doing Direct3D. It's faster, *easier*, and supported.

Share this post


Link to post
Share on other sites
It might help you understand what's failing if you check the return values from IDirectDrawSurface7::Blt.

Can the lpDDBltFx parameter be NULL or do you always have to pass a valid pointer even if your flags indicate it's not necessary for the blit?

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Quote:
Original post by Telastyn
Indeed. Replacing a half dozen lengthy loading functions with D3DXCreateTextureFromFile() is bound to decrease even the most stalwart DDraw fans.


LOL! You just got told.

Seriously though, stop doing DirectDraw IMMEDIATELY. Now start doing Direct3D. It's faster, *easier*, and supported.


eh? I was not being malicious. Just making an observation. Given the tone of the OP and the shape of the code, I'd wager that D3D is unavailable to them as they're working with an existing codebase.

My appologies if it sounded malicious, I was a bit snarky due to some other posts yesterday.

Share this post


Link to post
Share on other sites
Thats ok. I'm learning DirectDraw because thats what my book is on. After I do my shitty 2D project, I'll upgrade to D3D, and learn that. You just have to take it one step at a time! ;) I"ll try some of the other suggestions now. If you could ppost that code Anonymous Poster, i'd be very gratful!

Share this post


Link to post
Share on other sites
erm..honestly not sure how I would get that. Anyideas how I would find that out? Everytime I put a break into my code, the app crashs. Guess DX doesn't like being broken...;)

Share this post


Link to post
Share on other sites
Im not so sure, but you can also query for another DirectDraw Interface. Like the interface for version 4 or 6. If you need to know how, Ill tell ya.

Share this post


Link to post
Share on other sites
If the function returns an HRESULT and you put an if around it, it SHOULD fail since S_OK = 0. So the function call actually is working.


To get the actual code try this:

HRESULT hr = Blt(...);
char buf[16];
sprintf(buf, "%x\n", hr);
MessageBox(NULL, buf, "HRESULT returned from Blt", MB_OK);

That should give you the error code (in hex), je croix.

Share this post


Link to post
Share on other sites
Hello

Well I really suggest you take a deep look at the CDX library (http://www.cdxlib.com/), it is a set of well documented and easy to follow DirectX wrapper classes and best of all, comes with FULL SOURCE CODE!. I learned a lot from it.

Hope it helps you.
Oscar

Share this post


Link to post
Share on other sites
Quote:
Original post by ms291052
If the function returns an HRESULT and you put an if around it, it SHOULD fail since S_OK = 0. So the function call actually is working.


To get the actual code try this:

HRESULT hr = Blt(...);
char buf[16];
sprintf(buf, "%x\n", hr);
MessageBox(NULL, buf, "HRESULT returned from Blt", MB_OK);

That should give you the error code (in hex), je croix.

[edit] Got it thx for the code: 80070057 does this help?

I tried using the code from the ddutil.cpp/.h files, and *that* function comes back false. So the bitmap isn't even loading...

Share this post


Link to post
Share on other sites
HRESULT: 0x80070057 (2147942487)
Name: E_INVALIDARG
Description: An invalid parameter was passed to the returning function
Severity code: Failed
Facility Code: FACILITY_WIN32 (7)
Error Code: 0x0057 (87)

One or more of the parameters you're passing to Blt is wrong.

Share this post


Link to post
Share on other sites
1) Are you 100% sure the creation and loading of the bitmap from DDback_sprite is being loaded ok (filenames, formats, your loading code, etc ?). Check those error return codes for all DirectDraw and GDI calls!

2) As an experiment try taking DDSCAPS_VIDEOMEMORY out of your MercuryEngine::CreateSurface function.

3) Are you 100% certain that the bitmap being loaded is 800x600 and your surface is being created at that size? If it's smaller, then you could get the errors you've posted.

4) With DirectDraw (and D3D for that matter), it's a really good idea to make your application/engine work in windowed mode. In windowed mode you have easy access to the debugger window so can single step and see watches on variables etc. Get your application working first, then move to fullscreen, then fix any fullscreen issues (lost surfaces etc).

Share this post


Link to post
Share on other sites
Well like I said, when I try using the Bitmap load functions from ddutil.cpp/h, the bitmap isn't loaded... But i don't know why...


LPDIRECTDRAW7 lpdd; //version 7.0 main
...
...
if(FAILED(DDback_sprite = DDLoadBitmap(lpdd,"E:\\MyDocs\\Chris\\Programing\\DirectX\\MERC Engine\\lvl2.bmp",800,600)));
{
Application->MessageBoxA("DDLoadBitmap Failed","BOOM",MB_OK);
Application->Terminate();
}


Share this post


Link to post
Share on other sites
You can't use the FAILED macro to test the return value of DDLoadBitmap. It isn't returning an HRESULT, it's returning an IDirectDrawSurface7*.

From ddutil.h:

IDirectDrawSurface7 *DDLoadBitmap(IDirectDraw7 *pdd, LPCSTR szBitmap, int dx, int dy);

If DDLoadBitmap were failing and return NULL, the FAILED macro would interpret this as DD_OK (which is defined as 0) and would think the call actually succeeded.

Share this post


Link to post
Share on other sites
OMFG! Finally got it! O.o I changed that code, but how to you test for a fail? I tried a few things, but each one kept conplaing, reporting a fail of the load. I got frustrated and made a new BMP file (the one I was using worked in other apps) and POOF! It loaded just like that. I was so choked! Thank you all for your help, I really appreciate it!

Sigma

Share this post


Link to post
Share on other sites

This topic is 4812 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this