Saving a Screen Shot in DirectX Graphics

Home | Up | Search | X-Zone News | Services | Book Support | Links | Feedback | Smalltalk MT | The Scrapyard | FAQ | Technical Articles

 

Edited by Robert Dunlop
Microsoft DirectX MVP

Based on an original article by Eric DeBrosse
at mvps.org/vbdx/

The original article written for Visual Basic can be found at
http://www.mvps.org/vbdx/articles/screenshot/

Related Articles of Interest:

Rendering Full Screen Images from Textures
Rendering 3D Scenes to Large Image Formats

With the release of the DirectX 8.1 SDK, new functions were introduced to the D3DX libraries providing pre-canned routines to write image files from DirectX resources.  These functions allow surface, texture, and volume resources to be stored to disk as either BMP or DDS files.  In this article, we will examine a function to save a screen shot from a VC++ application using the DirectX 8.1 SDK.

In previous versions of DirectX, we might have locked the primary surface and read the pixel data from the frame buffer.  However, as of the release of DirectX 8, direct access to the primary surface memory is no longer available.  Instead, the GetFrontBuffer() provides a facility to retrieve the contents of the frame buffer to an image surface in system memory.  Format conversion is automatically performed, converting from the current display format to a fixed format of A8R8G8B8.

Our function will take two parameters, a pointer to the current device and a pointer to a null terminated string containing the file name of the BMP to be created.  The function will return D3D_OK on success, or pass the error code returned by the last function on failure.  The first thing that we must do is create an image surface the size of the display, with a format of D3DFMT_A8R8G8B8:

HRESULT ScreenGrab(LPDIRECT3DDEVICE8 pDev,char *fileName)
{
	HRESULT hr;

	// get display dimensions
	// this will be the dimensions of the front buffer
	D3DDISPLAYMODE mode;
	if (FAILED(hr=pDev->GetDisplayMode(&mode)))
		return hr;

	// create the image surface to store the front buffer image
	// note that call to GetFrontBuffer will always convert format to A8R8G8B8
	LPDIRECT3DSURFACE8 surf;
	if (FAILED(hr=pDev->CreateImageSurface(mode.Width,mode.Height,
						D3DFMT_A8R8G8B8,&surf)))
		return hr;

Next, this surface is passed to the GetFrontBuffer() method of the device, which will copy the entire screen into our image buffer:

	// read the front buffer into the image surface
	if (FAILED(hr=pDev->GetFrontBuffer(surf))) {
		surf->Release();
		return hr;
	}

Finally, we call D3DXSaveSurfaceToFile() to create the BMP file, and release the temporary image surface:

	// write the entire surface to the requested file
	hr=D3DXSaveSurfaceToFile(fileName,D3DXIFF_BMP,surf,NULL,NULL);

	// release the image surface
	surf->Release();

	// return status of save operation to caller
	return hr;
}

Related Articles of Interest:

Rendering Full Screen Images from Textures
Rendering to Multiple Windows
Rendering 3D Scenes to Large Image Formats

This site, created by DirectX MVP Robert Dunlop and aided by the work of other volunteers, provides a free on-line resource for DirectX programmers.

Special thanks to WWW.MVPS.ORG, for providing a permanent home for this site.

Visitors Since 1/1/2000: Hit Counter
Last updated: 07/26/05.