Archived

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

Bitmap locked, invalid surface data...

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

DirectX is at it again! I lock a bitmap, nothing I haven''t done before... I retrieve the Lpitch for the bitmap, nothing new either... The surface data is stored in a variable called bBuffer of type dword*. Now this is the annoying part: I know that at (39,0) in the bitmap surface, the color is RGB32(0,255,0). Anyways, when I check for this: if(bBuffer[39]!=RGB32(0,255,0)){DisplayErrorMessage...} Error... When I perform this checking the bitmap is locked. Please correct me if I''m wrong, but the first pixel in the bitmap surface is bBuffer[0], and the pixel in (0,1) is bBuffer[bPitch]. bPitch holds the correct value. Any ideas how this can be fixed? What am I doing wrong? Why does directX hate me? I''ll post code if necessary, only I have no idea where to begin. To be continued... Any information which''s value ranges from 2 cents and up is greatly appreciated in advance.

Share this post


Link to post
Share on other sites
One more thing I just noticed which seems really odd.
I create all bitmaps using MsPaint, yet they seem to be of different resolutions.
The working bitmap is 692*31, and is 22Kb, which means each pixel uses 1 bye.
The none working bitmap is 48*297, and is 41.8Kb in size -> 3 bytes per pixel...
I initialized directX to a resolution of 32 bits per pixel, 1024*768...
Why does MsPaint generate bitmaps of different resolutions? - Is it because I was working under windows when it was under a different type of resolution? Probably...

Any type of help [2 cents and less as well] would be grealy appreciated.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
It depends on how you save your bitmap. The save menu gives you options including 24-bit bitmap(3 bytes per pixel) and 256 Color bitmap (1 bpp). You have to specify how you want to save each bitmap.

Share this post


Link to post
Share on other sites
Each pixel isn''t necessarily represented by 1 byte. As AP said, you can have different image formats. If your textures are 32-bit, then each pixel in fact requires four bytes. So you can use something like:

LPDWORD dwBuffer = (LPDWORD) bBuffer;
if (dwBuffer[39] !- RGB32(0, 255, 0)) ...

Note that your code compares a byte to a dword while my code compares two dwords.

All textures must have sizes that are power of two: 256x256, 1024x32, etc. If you load a non-power-of-two texture using D3DX, D3DX will convert it to proper dimensions. However, your texture coords may refer to different image area. So you should always create power-of-two bitmaps for your textures to avoid troubles.

Share this post


Link to post
Share on other sites
Thanks, but the 256 color bitmap works nicely with my code [when the lPitch is not in use]. It''s the 24Bit image that doesn''t - and I am dividing the lPitch by 4.
The bitmap loading functions is doing its job propperly so far -
when the image is used for blitting.
But when I lock it and try to access the pixels it seems somewhat VERY buggy and flawed.

Should l_pitch be divided by 3 instead of 4, after all the bitmap is 24bps. Direct Draw, however, is initialized to 32bps because 24bps is not widely supported [on my pc at least].

Anyhow, the l_pitch does not seem to be the only problem if at all.
bBuffer[5] will not access the 6th [including 0] pixel on the X axis at coordinate (5,0)...
Should I question my bitmap loading function, or is there something else I''m doing wrong?

Thanks for the support.

Share this post


Link to post
Share on other sites
The bitmap loading function is perfectly fine...
The sad part is that I really wanted it to be the bug, would make my job a whole lot easier...

while(user_is_annoyed)
{
lpdd->DriveUser(CRAZY);
if(gamedev.Post(recent)==GOOD)
break;
}

Aspirin tablets are greatly appreciated.

Share this post


Link to post
Share on other sites
Show us some code, dude!

Are you loading the bitmap the easy way? The easy way simply involves creating your surface, using GetDC, LoadImage, BitBlt, then ReleaseDC (with maybe one or two steps in between). That method will automatically convert between colour depths so if you did that then you''d have a bug writing to your 32 bit value, not loading it.

If you''re manually loading the bitmap without using BitBlt (I dunno, locking and writing to the surface for copying by hand) then you''d have trouble - the bitmap will be 24bpp so you''ll have to pad it with an extra byte each time. If you didn''t do that then the colours would be *very* screwy.

In both cases, when you''ve got your surface you will be dealing with 32 bits per pixel (because that''s what you''ve set up).

Share this post


Link to post
Share on other sites
I usually don't throw lines of code at people waiting for them to do the work. So if it's too much, a few pointers and tips would be perfectly fine.

BMP LoadBitmap(char* file,int width, int height,dword lowclrkey,dword highclrkey)
{
HBITMAP hbm;
BITMAP bm;
LPDIRECTDRAWSURFACE7 lpdds;

if(highclrkey==NULL){highclrkey=lowclrkey;} //By default

//Try to load the bitmap as a resource, if that fails, try it as a file
hbm = (HBITMAP)LoadImage(GetModuleHandle(NULL),file,IMAGE_BITMAP,width,height,LR_CREATEDIBSECTION);

if(hbm==NULL)
hbm = (HBITMAP)LoadImage(NULL,file,IMAGE_BITMAP,width,height,LR_LOADFROMFILE|LR_CREATEDIBSECTION);

if(hbm==NULL)
{ErrorBox("BMP: Unable to load the bitmap!"); 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_WIDTH|DDSD_HEIGHT|DDSD_CKSRCBLT;
ddsd.ddsCaps.dwCaps=DDSCAPS_OFFSCREENPLAIN|DDSCAPS_VIDEOMEMORY;
ddsd.dwWidth=bm.bmWidth;
ddsd.dwHeight=bm.bmHeight;

ddsd.ddckCKSrcBlt.dwColorSpaceLowValue=lowclrkey;
ddsd.ddckCKSrcBlt.dwColorSpaceHighValue=highclrkey;

if(FAILED(lpdd->CreateSurface(&ddsd, &lpdds, NULL)))
{
ErrorBox("DDraw error: Unable to create an offscreen surface for the bitmap!");
return NULL;
}

HDC hdcImage;
HDC hdc;

if (hbm == NULL || lpdds == NULL)
return NULL;

//Select bitmap into a memoryDC so we can use it.
hdcImage = CreateCompatibleDC(NULL);

if(!hdcImage)
{ErrorBox("DDraw Error: Unable to create the device context!"); return NULL;}

SelectObject(hdcImage, hbm);

if(!FAILED(lpdds->GetDC(&hdc)))
{
StretchBlt(hdc,0,0,ddsd.dwWidth,ddsd.dwHeight,hdcImage,0,0,width,height,SRCCOPY);
lpdds->ReleaseDC(hdc);
}
DeleteDC(hdcImage);

DeleteObject(hbm);
return lpdds;
}

//BMP is identical to LPDIRECTDRAWSURFACE7

[edited by - origil on June 3, 2002 5:29:17 AM]

Share this post


Link to post
Share on other sites
Looks like you've got the usual stuff for loading bitmaps so that's probably not the problem.

It seems that it's your lock->pixel manipulation that's going wrong here. Assuming that the loading code is right and that you've successfully loaded the bitmap onto the surface, you'll want something like the following:

  DDSURFACEDESC2 ddsd2;


memset(&ddsd2, 0, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
YourSurface->Lock(NULL, &ddsd2, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);

int pitch = ddsd2.lPitch >> 2;
DWORD* pixels = (DWORD*)ddsd2.lpSurface;

// now do whatever

pixels[5] = 0x00FFAA22;
pixels[pitch + 5] = 0x0022FFAA;
pixels[2*pitch + 5] = 0x001234FF;

YourSurface->Unlock(NULL);

(Apologies if the above code doesn't compile as is - I usually use Delphi for DirectDraw things.)

Post your pixel manipulation code as well if the above doesn't look like it sorts out the problem.

P.S. Hahaha! Brazil are losing 1-0 to Turkey LOL!

[edited by - Alimonster on June 3, 2002 6:02:58 AM]

Share this post


Link to post
Share on other sites
dword* LockBitmap(BMP bitmap, int *b_pitch)
{
DDSURFACEDESC2 ddsdBmp; //Bitmap surface information
dword* bitmapSurface;
ZeroMemory(&ddsdBmp,sizeof(ddsdBmp)); //Init surface description
ddsdBmp.dwSize = sizeof(ddsdBmp);

if(FAILED(bitmap->Lock(NULL, &ddsdBmp,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL)))
{ErrorBox("DDraw error: Unable to lock the image surface!");}

if(b_pitch!=NULL)*b_pitch = (int)ddsdBmp.lPitch>>2;

bitmapSurface = (dword *)ddsdBmp.lpSurface;

return bitmapSurface;
}

Everything seems fine...

typedef unsigned long dword;
...
...
The lock and unlock seemed to work nicely with surfaces I created which did not load bitmaps.
I''ll compare them though they were originally created using copy and paste, maybe there''s something I missed in the comparison...

Share this post


Link to post
Share on other sites
Ok, it is final.
I am going mad!

After locking the bitmap:
I ran a testing algorithm on the bitmap data, located on bBuffer,

    
for(int i=0;i<bmpWidth;i++)
{
if(bBuffer[i]==RGB32(0,0,255)) //If pixel is Blue

{bBuffer[i]=RGB32(0,255,0);} //Change color to Green

}


Note that ALL the pixels I was testing were blue to begin with and were changed to green according to the algorithm.

I ran this test again twice, using green and red as the tested pixels.
All pixels were red or green according to the test, and only HALF of them were changed.
Only the even including the first pixel were changed...
I assume this is because red and green have higher values than blue which is only 0xFF. - Fits into 1 byte.
These are the conclusions I have come to:

1) Programming should be made illegal.
2) My bitmap loading function DOES NOT support 24BPP bitmaps!
3) OOOhhh... pretty colows....
4) The world is not flat.
5) Appreciate people's help.
6) Find out what that grey button saying "Reply to topic" does before you can finish typing thi

[edited by - origil on June 3, 2002 12:49:20 PM]

Share this post


Link to post
Share on other sites
Woohhhhoooo!
Just found out what the problem was!
In order for noone to repeat my stupid mistakes, here''s the problem:
dword contains 4 bytes, the bitmap contains 3 bytes per pixel.
So what went wrong? The 4th byte in some of the pixels contained the value FF.
The bitmap was still blitted correctly but when the value was tested blue was not 000000FF (FF), it was FF0000FF.

Share this post


Link to post
Share on other sites