Archived

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

octavsoft

Saving BMP's to disk in directDRAW

Recommended Posts

I''m working on an RPG called Ancient and I want to add support for screenshoots. I''m using DIRECTDRAW. The mode is 800x600x16 bpp. If I use the printscreen key the image in the clipboar is awfull, I thing cause it should be 16 bpp, but it is actually 8 bpp in the clipboard I want to save the image to a file. I made everything, the creation of the file, writeing the headers, but I can''t get the image from the DD surface to an array, so I can write it to the disk. Can anyone help me? Octavian e-mail: octavsoft@octavsoft.freeservers.com webpag: octavsoft.freeservers.com

Share this post


Link to post
Share on other sites
Hi, this isn''t originally my code, but I''ve made some changes to it to suit my purposes. It''ll dump a bitmap out in 16bpp, at scale SCALE. I only know for SURE that it works in 640x480x16, with SCALE defined as 1, 2, or 3. If you define SCALE as 2 or 3, you get 1/2 the size and 1/3 the size, respectively. Also, watch out for OR statements-- like this: DDSCAP_PRIMARYSURFACE/DDSCAPS_FLIP. The forum, for some reason, take the OR symbol and turns it into a division symbol.

I use this routine to run in the background to capture screens for binding into AVI movies.



#define SCALE 2

BOOL SaveBMP (LPDIRECTDRAWSURFACE SaveSurface, LPDIRECTDRAWSURFACE FrontBuffer,const char * szFilename) {
HANDLE file_out;

file_out = CreateFile(szFilename,GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(file_out == INVALID_HANDLE_VALUE) return FALSE;
SaveBMPToFile(SaveSurface,FrontBuffer,file_out);
CloseHandle(file_out);

return TRUE;
}

BOOL SaveBMPToFile(LPDIRECTDRAWSURFACE SaveSurface,LPDIRECTDRAWSURFACE FrontBuffer, HANDLE file_out) {
HRESULT rval;
DWORD numwrite;
BITMAPFILEHEADER fh;
BITMAPINFOHEADER bi;
DWORD outpixel;
int outbyte, loop, loop2, BufferIndex;
BYTE *WriteBuffer;
DDSURFACEDESC ddsd;
int Width, Height, Pitch;
BYTE *Bitmap_in;
LPDIRECTDRAWPALETTE Pal;
char bytepal [256*4];
short rowcount;
short fixwidth;

ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
rval = SaveSurface->lpVtbl->GetSurfaceDesc (SaveSurface,&ddsd);
if (rval != DD_OK) return FALSE;

BufferIndex = 0;
Width = ddsd.dwWidth;
Height = ddsd.dwHeight;
Pitch = ddsd.lPitch;
if (SCALE==3) Width=216*3;

WriteBuffer = malloc((Width*Height)*3); //width*height*24-bit


((char *)&(fh . bfType))[0] = ''B'';
((char *)&(fh . bfType))[1] = ''M'';
fh . bfSize = (long)(sizeof (BITMAPINFOHEADER)+sizeof (BITMAPFILEHEADER)+Width*Height*3); //Size in BYTES
fh . bfReserved1 = 0;
fh . bfReserved2 = 0;
fh . bfOffBits = sizeof (BITMAPINFOHEADER)+sizeof (BITMAPFILEHEADER);
bi . biSize = sizeof (BITMAPINFOHEADER);
bi . biWidth =Width/SCALE;
bi . biHeight =Height/SCALE;
bi . biPlanes = 1;
bi . biBitCount = 24;
bi . biCompression = BI_RGB;
bi . biSizeImage = 0;
bi . biXPelsPerMeter = 10000;
bi . biYPelsPerMeter = 10000;
bi . biClrUsed = 0;
bi . biClrImportant = 0;

WriteFile (file_out, (char *) &fh,sizeof (BITMAPFILEHEADER),&numwrite,NULL);
WriteFile (file_out, (char *) &bi,sizeof (BITMAPINFOHEADER),&numwrite,NULL);
if (ddsd.ddpfPixelFormat.dwRGBBitCount==16) { //16 bit surfaces
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
rval=SaveSurface->lpVtbl->Lock(SaveSurface,NULL,&ddsd, DDLOCK_WAIT,NULL);
if (rval != DD_OK) {
free(WriteBuffer);
return FALSE;
}

Bitmap_in = (BYTE*)ddsd.lpSurface;
if (ddsd .ddpfPixelFormat . dwGBitMask == 0x07E0) {
for (loop =Height-1;loop>=0;loop-=SCALE) { //Loop bottom up
rowcount=0;
for (loop2=0;loop2 outpixel = *((WORD *)(Bitmap_in+loop2*2 + loop * Pitch)); //Load a word
outbyte = (8*((outpixel)&0x001f));//blue
*(WriteBuffer+BufferIndex)=outbyte;
BufferIndex++;
outbyte = (4*((outpixel>>5)&0x003f));
*(WriteBuffer+BufferIndex)=outbyte;
BufferIndex++;
outbyte = (8*((outpixel>>11)&0x001f));
*(WriteBuffer+BufferIndex)=outbyte;
BufferIndex++;

rowcount++;
}
// You would need to PAD your bmp file...
}

// Okay, it didn''t work for /3 because I need to
// pad my bitmap to be divisible by 4...

}
else {
for (loop =Height-1;loop>=0;loop-=SCALE) { //Loop bottom up
rowcount=0;
for (loop2=0;loop2 outpixel = *((WORD *)(Bitmap_in+loop2*2 + loop * Pitch)); //Load a word
outbyte = (8*((outpixel)&0x001f));//blue
*(WriteBuffer+BufferIndex)=outbyte;
BufferIndex++;

outbyte = (8*((outpixel>>5)&0x001f));
*(WriteBuffer+BufferIndex) = outbyte;
BufferIndex++;

outbyte = (8*((outpixel>>10)&0x001f)); //BUG FIX here
*(WriteBuffer+BufferIndex) = outbyte;
BufferIndex++;
rowcount++;
}
}
}

WriteFile (file_out, WriteBuffer,BufferIndex,&numwrite,NULL);
IDirectDrawSurface_Unlock(SaveSurface,ddsd.lpSurface);
}

free(WriteBuffer);
return TRUE;
}


-- Goodlife

-----------------------------
Think of your mind as a door on a house. Leave the door always closed, and it's not a house, it's a prison. Leave the door always open, and it's not a house, it's a wilderness-- all the vermin creep in.

Share this post


Link to post
Share on other sites
Thanks, Goodlife

It helped. After corecting few errors ( some because I use C++ and the code was using C and another one in the second for loop, both in 555 an 565 modes, there was something missing ) it wworke perfectly.
Thanks very much and visit my webpage in the Projects, Ancient section so you''ll see the result of your work in the scrrenshoots. Enter there in a ay or so (if you enter now you''ll see the old scrrenshoot). My address is: octavsoft.freeservers.com

Octavian
e-mail: octavsoft@octavsoft.freeservers.com
webpag: octavsoft.freeservers.com

Share this post


Link to post
Share on other sites
Well , try this: enable print Screen key under directx control in the control panel (under the Direct draw Tab ). During the game , I press print scr , and paste in photoshop or whatever and bingo .............

Share this post


Link to post
Share on other sites
Hey, no problem Oct... sorry about the errors-- but like I said, I wired the code to do exactly what I wanted it to do, because I got the actual BMP routines from somewhere else.

I tried to check out your web page, but my computer stopped all activity for so long that I guess either your server was down or I was hitting some sort of blockade across ISPland (probably the latter, because all of the internet slowed down for me).

So I''ll try to check it out tomorrow. Take care!

Share this post


Link to post
Share on other sites