This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.

 

  DX8 Surface To TGA
  Submitted by



During the development of any 3D engine itÂ’s probably that many times you need to save to a file the content of a surface or to take a snapshot of the backbuffer. With the incoming of DirectX 8 you need to change the way you did it in past, so I have write some functions to make it work. The cpp has these 3 functions:

HRESULT SaveSurfaceToTGAFile(LPDIRECT3DDEVICE8 pD3DDevice, const char *szFileName, LPDIRECT3DSURFACE8 pSurface); HRESULT SaveSurfaceToGrayscaleTGAFile(LPDIRECT3DDEVICE8 pD3DDevice, const char *szFileName, LPDIRECT3DSURFACE8 pSurface); HRESULT CaptureScreenToFile(LPDIRECT3DDEVICE8 pD3DDevice); Hope you find useful all of them. Regards
David

Download Associated File: SaveSurfaceToFile.cpp (8,064 bytes)

//
// SaveSurfaceToFile.cpp
//
// Copyright (c) 2001 David Galeano
//
// Permission to use, copy, modify and distribute this software
// is hereby granted, provided that both the copyright notice and 
// this permission notice appear in all copies of the software, 
// derivative works or modified versions.
//
// THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
// CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES 
// WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
//

#define DIRECT3D_VERSION	0x0800

#include <d3d8.h>

#include <stdio.h>

//----------------------------------------------------------------------------- // // SaveSurfaceToTGAFile // //----------------------------------------------------------------------------- HRESULT SaveSurfaceToTGAFile(LPDIRECT3DDEVICE8 pD3DDevice, const char *szFileName, LPDIRECT3DSURFACE8 pSurface) { HRESULT hr=S_OK;

D3DSURFACE_DESC d3dsd; LPDIRECT3DSURFACE8 pSurfaceCopy;

pSurface->GetDesc(&d3dsd);

hr=pD3DDevice->CreateImageSurface(d3dsd.Width, d3dsd.Height, d3dsd.Format, &pSurfaceCopy);

if(SUCCEEDED(hr)) { hr=pD3DDevice->CopyRects(pSurface, NULL, 0, pSurfaceCopy, NULL);

// save the copy to the file D3DLOCKED_RECT d3dLR; if(SUCCEEDED(hr = pSurfaceCopy->LockRect(&d3dLR, NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) { // open file FILE *pFile=fopen(szFileName, "wb"); if(pFile!=NULL) { setvbuf(pFile, NULL, _IOFBF, 64*1024);

// write header char targaheader[18];

// Set unused fields of header to 0 memset(targaheader, 0, sizeof(targaheader));

targaheader[2] = 2; /* image type = uncompressed RGB */ targaheader[12] = (char) (d3dsd.Width & 0xFF); targaheader[13] = (char) (d3dsd.Width >> 8); targaheader[14] = (char) (d3dsd.Height & 0xFF); targaheader[15] = (char) (d3dsd.Height >> 8); targaheader[16] = (d3dsd.Format==D3DFMT_A8R8G8B8 || d3dsd.Format==D3DFMT_A1R5G5B5 ? 32 : 24); targaheader[17] = 0x20; /* Top-down, non-interlaced */

fwrite(targaheader, 18, 1, pFile);

// write file const BYTE *pImage=(const BYTE *)d3dLR.pBits; for(DWORD y=0; y<d3dsd.Height; y++) { if(d3dsd.Format==D3DFMT_X8R8G8B8) { const BYTE *pImageAux=pImage; for(DWORD x=0; x<d3dsd.Width; x++) { putc(pImageAux[0], pFile); putc(pImageAux[1], pFile); putc(pImageAux[2], pFile); pImageAux+=4; } } else if(d3dsd.Format==D3DFMT_A8R8G8B8) { fwrite(pImage, d3dsd.Width, 4, pFile); } else if(d3dsd.Format==D3DFMT_R5G6B5) { const BYTE *pImageAux=pImage; for(DWORD x=0; x<d3dsd.Width; x++) { const DWORD dwColor=*((WORD *)pImageAux);

BYTE color;

color=BYTE((dwColor&0x001f)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x7e0)>>5)<<2); putc(color, pFile);

color=BYTE(((dwColor&0xf800)>>11)<<3); putc(color, pFile);

pImageAux+=2; } } else if(d3dsd.Format==D3DFMT_X1R5G5B5) { const BYTE *pImageAux=pImage; for(DWORD x=0; x<d3dsd.Width; x++) { const DWORD dwColor=*((WORD *)pImageAux);

BYTE color;

color=BYTE((dwColor&0x001f)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x3e0)>>5)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x7c00)>>10)<<3); putc(color, pFile);

pImageAux+=2; } } else if(d3dsd.Format==D3DFMT_A1R5G5B5) { const BYTE *pImageAux=pImage; for(DWORD x=0; x<d3dsd.Width; x++) { const DWORD dwColor=*((WORD *)pImageAux);

BYTE color;

color=BYTE((dwColor&0x001f)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x3e0)>>5)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x7c00)>>10)<<3); putc(color, pFile);

color=BYTE(((dwColor&0x8000)>>15)*255); putc(color, pFile);

pImageAux+=2; } }

pImage+=d3dLR.Pitch; }

fclose(pFile); }

pSurfaceCopy->UnlockRect(); }

pSurfaceCopy->Release(); }

return hr; }

//----------------------------------------------------------------------------- // // SaveSurfaceToGrayscaleTGAFile // //----------------------------------------------------------------------------- HRESULT SaveSurfaceToGrayscaleTGAFile(LPDIRECT3DDEVICE8 pD3DDevice, const char *szFileName, LPDIRECT3DSURFACE8 pSurface) { HRESULT hr=S_OK;

LPDIRECT3DSURFACE8 pSurfaceCopy=NULL;

D3DSURFACE_DESC d3dsd;

pSurface->GetDesc(&d3dsd);

if(d3dsd.Pool!=D3DPOOL_SYSTEMMEM) { hr=pD3DDevice->CreateImageSurface(d3dsd.Width, d3dsd.Height, d3dsd.Format, &pSurfaceCopy);

if(SUCCEEDED(hr)) { hr=pD3DDevice->CopyRects(pSurface, NULL, 0, pSurfaceCopy, NULL); } } else { pSurfaceCopy=pSurface; }

if(SUCCEEDED(hr)) { // save the copy to the file D3DLOCKED_RECT d3dLR; if(SUCCEEDED(hr = pSurfaceCopy->LockRect(&d3dLR, NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY))) { // open file FILE *pFile=fopen(szFileName, "wb"); if(pFile!=NULL) { setvbuf(pFile, NULL, _IOFBF, 64*1024);

// write header char targaheader[18];

// Set unused fields of header to 0 memset(targaheader, 0, sizeof(targaheader));

targaheader[2] = 3; /* image type = uncompressed gray-scale */ targaheader[12] = (char) (d3dsd.Width & 0xFF); targaheader[13] = (char) (d3dsd.Width >> 8); targaheader[14] = (char) (d3dsd.Height & 0xFF); targaheader[15] = (char) (d3dsd.Height >> 8); targaheader[16] = 8; targaheader[17] = 0x20; /* Top-down, non-interlaced */

fwrite(targaheader, 18, 1, pFile);

// write file const BYTE *pImage=(const BYTE *)d3dLR.pBits; for(DWORD y=0; y<d3dsd.Height; y++) { const BYTE *pImageAux=pImage; for(DWORD x=0; x<d3dsd.Width; x++) { if(d3dsd.Format==D3DFMT_X8R8G8B8 || d3dsd.Format==D3DFMT_A8R8G8B8) { // save average greyscale putc((pImageAux[0]+pImageAux[1]+pImageAux[2])/3, pFile); pImageAux+=4; } else if(d3dsd.Format==D3DFMT_R5G6B5) { const DWORD dwColor=*((WORD *)pImageAux);

DWORD colorAverage;

colorAverage=((((dwColor&0xf800)>>11)<<3|0x07)); colorAverage+=((((dwColor&0x7e0)>>5)<<2)|0x03); colorAverage+=(((dwColor&0x001f)<<3)|0x07); putc(colorAverage/3, pFile);

pImageAux+=2; } else if(d3dsd.Format==D3DFMT_X1R5G5B5) { // save only green chanel const DWORD dwColor=*((WORD *)pImageAux);

DWORD colorAverage;

colorAverage=((((dwColor&0x7c00)>>10)<<3)|0x07); colorAverage+=((((dwColor&0x3e0)>>5)<<3)|0x07); colorAverage+=(((dwColor&0x001f)<<3)|0x07); putc(colorAverage/3, pFile);

pImageAux+=2; } } pImage+=d3dLR.Pitch; }

fclose(pFile); }

pSurfaceCopy->UnlockRect(); } }

if(d3dsd.Pool!=D3DPOOL_SYSTEMMEM) { if(pSurfaceCopy!=NULL) { pSurfaceCopy->Release(); } }

return hr; }

//----------------------------------------------------------------------------- // // CaptureScreenToFile // //----------------------------------------------------------------------------- HRESULT CaptureScreenToFile(LPDIRECT3DDEVICE8 pD3DDevice) { HRESULT hr=S_OK;

LPDIRECT3DSURFACE8 pBackBuffer;

if(SUCCEEDED(hr = pD3DDevice->GetRenderTarget(&pBackBuffer))) { char szName[MAX_PATH];

// find a free filename DWORD nIndFile=0; do { sprintf(szName, "screen%02u.tga", nIndFile); nIndFile++; } while(GetFileAttributes(szName)!=DWORD(-1));

SaveSurfaceToTGAFile(pD3DDevice, szName, pBackBuffer);

pBackBuffer->Release(); }

return hr; }

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.

 

Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.