Sign in to follow this  
pjneil

memcpy to dx7 surface

Recommended Posts

I have an issue loading a bitmap file and then copying it to a directx7 surface.
I have isolated the header files and checked all of the resulting values against the image that I am trying to load, they all seem ok.
However when I run it, the image does not display correctly.
I would very much appreciate somebody casting their eye over my code and perhaps giving me a few pointers

I have been chasing this round for a while now. Think I'm going a bit bonkers. - code follows Cheers.


[code]

void
Bitmap::LoadBMP(const char *filename, const char *mode, bool isRLE)
{
HBITMAP hbm;
BITMAP bm;
FILE *m_bitMapFile;
PVOID* pixData;
DDSURFACEDESC2 ddsd;
BYTE* surfacePointer;
//HDC hdcImage;

m_bitMapFile = fopen(filename,mode);//open the file for binary reading
//structures defined in winGDi.h
//describing .bmp header information
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
BITMAPINFO bmi;
BITMAPINFO bmi2;

fread(&bmfh,sizeof(BITMAPFILEHEADER),1,m_bitMapFile);// Read the file header info into bmfh
fread(&bmi,sizeof(BITMAPINFO),1,m_bitMapFile);
//fread(&bmih,sizeof(BITMAPINFOHEADER),1,m_bitMapFile);// Read the info header info into bmih


//GetObject(m_bitMapFile,sizeof(bmi),&bmi);

//Now that we have isolated the header info
//A check to ensure the file is a bitmap
//a value of 19778 (0x4d42) should be in BITMAPFILEHEADER.bfType

WORD isBitmap = bmfh.bfType;
if (isBitmap != 19778)
{
/*
include some error response here
*/
//return false;
}//OK we have a bitmap

//fclose(m_bitMapFile);

//Create our internal DirectDraw surface using values taken from the loaded bmp
//first thing to do is reserve some memory for ddsd.
//This will be passed to the CopyToInternalSurface
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = bmi.bmiHeader.biWidth;
ddsd.dwHeight = bmi.bmiHeader.biHeight;
ddsd.ddpfPixelFormat.dwFlags = DDPF_COMPRESSED;
ddsd.ddpfPixelFormat.dwRGBBitCount = bmi.bmiHeader.biBitCount;
DirectDraw::GetInstance()->GetDirectDrawObject()->CreateSurface(&ddsd, &m_bitmapSurface, NULL);


//Check to see if any compression is in use
// 0 = none, if this is true the wronf function has been called - return
// 1 = RLE 8-bit/pixel,Decode before copying to Surface
// 2 = RLE 4-bit/pixel, Decode before copying to surface
//decisions can be made for decoding based on this value.
unsigned int compressed = bmi.bmiHeader.biCompression;

if (compressed == 0)//no compression
{
//find the size of the image data
//subtracting to offBits from the size is the most accurate way of doing this.
DWORD size;
size = bmfh.bfSize - bmfh.bfOffBits;
//DWORD size = bmi.bmiHeader.biSizeImage;
temppixelData = new BYTE[size];
size_t result;
//fseek(m_bitMapFile,bmfh.bfOffBits,SEEK_SET);
result = fread(temppixelData,sizeof(BYTE),size,m_bitMapFile);
int e = feof(m_bitMapFile);

//temppixelData now holds the raw image data.
if((m_bitmapSurface->Lock(NULL,&ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK | DDLOCK_WRITEONLY, NULL))==DD_OK);
{
surfacePointer = (BYTE*)ddsd.lpSurface;

for(int y=0; y < bmi.bmiHeader.biHeight; y++)
{
memcpy(surfacePointer +y*ddsd.lPitch, temppixelData+y*ddsd.dwWidth, ddsd.dwWidth*ddsd.ddpfPixelFormat.dwRGBBitCount);
}
}

m_bitmapSurface->Unlock(NULL);
m_bitmapwidth = bmi.bmiHeader.biWidth;
m_bitmapheight = bmi.bmiHeader.biHeight;
fclose(m_bitMapFile);

}



else if (compressed ==1)//RLE 8
{



}
else if (compressed ==2)//RLE 4
{
//check for pallete then decode
}
}
[/code]

Share this post


Link to post
Share on other sites
Break into the debugger or log the values before you do the copy, and make sure the values obtained for the locked surface are what you expect.
In particular, ddsd.ddpfPixelFormat.dwRGBBitCount is in bits, not bytes, so you need to divide it by 8.
Also, y*ddsd.dwWidth should probably be multiplied by the number of bytes per pixel.
Do you need to use the DDPF_COMPRESSED flag?
Not sure what exactly that will do..

Share this post


Link to post
Share on other sites
I'm confused. First of all you create the surface with compression, then you check if compression is used in the bitmap, you have a comment explicitly stating that if no compression is used we don't even attempt to load the bitmap, and finally you do the exact opposite - you load an uncompressed bitmap into a compressed surface and don't handle the compressed bitmap cases.

Share this post


Link to post
Share on other sites
Erik and mhagain, thanks for the reply. I will try these thing out. My reason for handling an uncompressed images was that I am new to this and I wanted to be sure that I was copying to the surface correctly before I move onto trying this with compressed data. I didnt want to come across issues later on that appeared to compression related that were infact relateing to the moving of the data. My BITMAP class already has a function to load an uncompressed image that works well, but I have a need to be able to handle RLE compression. Thanks again for your reply

Share this post


Link to post
Share on other sites
I think I am getting somewhere with this. it seems that the surface lock is changing the [color=#1C2837][color=#000000]ddsd[/color][color=#666600].[/color][color=#000000]ddpfPixelFormat[/color][color=#666600].[/color][color=#000000]dwRGBBitCount.[/color][/color]
[color=#1C2837][color=#000000]
[/color][/color]
[color=#1C2837][color=#000000]I cant imagine why.[/color][/color]
[color=#1C2837][color=#000000]Can any body?[/color][/color]

Share this post


Link to post
Share on other sites
It's also an output parameter, and it is supposed to change and tell you information about the surface you lock. The surface is already created and has a specific format, and you can't change that by locking it. The structure will be changed to reflect the actual contents of the surface, as that is the only type of data you can write to it with any reliable result.

Share this post


Link to post
Share on other sites
Hi Erik

So my surface is unchanged. I have also made the changes that you suggested earlier. I now see my image. the height is good. However the image width is not correct, it is squashed and is grey scale and the image background appears to have stripes. All of the other values are correct. could this be a problem with the DWORD boundary of the bitmap?

Share this post


Link to post
Share on other sites
Yes it could. Always read the Pitch, sometimes called row-bytes or similar, and use that to get the source and destination data for copying rows, as there may be padding. Also, make sure the bit-depth is the same in both source and destination, so you're not trying to copy 32 bit data to a 24 bit surface, or the other way around.

Share this post


Link to post
Share on other sites

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