Need help load .bmp files

Started by
21 comments, last by _Sigma 19 years, 6 months ago
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]
Advertisement
anyone?
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 :)
Indeed. Replacing a half dozen lengthy loading functions with D3DXCreateTextureFromFile() is bound to decrease even the most stalwart DDraw fans.
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 surfaceDDback->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 structureDDback->Blt(&dest_rect,DDback_sprite,&src_rect,DDBLT_WAIT, NULL);


and now my color fill works, but still no bitmap!
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 :)
I'll post my DirectDraw bitmap loader later...
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.
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?
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.

This topic is closed to new replies.

Advertisement