www.pudn.com > ImageSplite.rar > tgaapi.cpp
#include "stdafx.h"
#include "dibapi.h"
#include "tgaapi.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma pack(1)
struct TGA_FILE_HEADER
{
BYTE byIdLength;
BYTE byColorMapType;
BYTE byImageType;
short nColorMapFirstIndex;
short nColorMapLength;
BYTE byColorMapEntrySize;
short nXOrigin;
short nYOrigin;
short nImageWidth;
short nImageHeight;
BYTE byPixelDepth;
BYTE byImageDescriptor;
};
struct TGA_FILE_FOOTER
{
long lExtensionAreaOffset;
long lDeveloperDirectoryOffset;
char cSignature[18];
};
#pragma pack()
/*************************************************************************
*
* Function: ReadTGAFile (CFile&)
*
* Purpose: Reads in the specified targe file into a global chunk of
* memory.
*
* Returns: A handle to a dib (hDIB) if successful.
* NULL if an error occurs.
*
**************************************************************************/
HDIB ReadTGAFile(CFile& file)
{
//Determine if the file is in the original TGA format
//or the new TGA format i.e. post September 1989
DWORD dwFileLength = file.GetLength();
if (dwFileLength == 0)
return NULL;
file.Seek(dwFileLength - sizeof(TGA_FILE_FOOTER), CFile::begin);
TGA_FILE_FOOTER fileFooter;
file.Read(&fileFooter, sizeof(TGA_FILE_FOOTER));
BOOL bNewTGAFormat = FALSE;
if (strcmp(fileFooter.cSignature, "TRUEVISION-XFILE.") == 0)
bNewTGAFormat = TRUE;
//Read in the TGA file header
TGA_FILE_HEADER fileHeader;
file.SeekToBegin();
file.Read(&fileHeader, sizeof(TGA_FILE_HEADER));
//We only support 32 and 24 bit color depths
if ((fileHeader.byPixelDepth != 32) &&
(fileHeader.byPixelDepth != 24))
{
TRACE(_T("Bit depth is %d, which cannot be handled\n"), fileHeader.byPixelDepth);
return NULL;
}
//now read in the image data
if (fileHeader.byImageType != 2)
{
TRACE(_T("Image type is not an uncompressed true-color image, instead it is %d\n"), fileHeader.byImageType);
return NULL;
}
//check that the Color map type is 0
if (fileHeader.byColorMapType != 0)
{
TRACE(_T("Color map type is non zero in the TGA file header for this uncompressed true-color tga file, instead it is %d\n"), fileHeader.byColorMapType);
return NULL;
}
//Determine the end offset of the "Image Data"
DWORD dwEndImageData = 0;
if (bNewTGAFormat)
dwEndImageData = fileFooter.lExtensionAreaOffset - 1;
else
dwEndImageData = dwFileLength;
//Determine the start offset of the "Image Data" and the pointer to
//the color map
DWORD dwStartImageData = sizeof(TGA_FILE_HEADER) + fileHeader.byIdLength;
//Read in the image data
DWORD dwImageSize = dwEndImageData - dwStartImageData;
BYTE* pImageData = new BYTE[dwImageSize];
file.Seek(dwStartImageData, CFile::begin);
file.Read(pImageData, dwImageSize);
// initializing incapsulated image with correct values
BITMAPINFO bmi;
BITMAPINFOHEADER& bih = bmi.bmiHeader;
ZeroMemory(&bih, sizeof(BITMAPINFOHEADER));
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = fileHeader.nImageWidth;
bih.biHeight = fileHeader.nImageHeight;
bih.biCompression = BI_RGB;
bih.biPlanes = 1;
bih.biBitCount = 24;
//Allocate a buffer to use for the transfer to DIB format
DWORD imageSize = fileHeader.nImageHeight*(fileHeader.nImageWidth*3+((4-((fileHeader.nImageWidth*3)&3))&3));
BYTE* pBmp = new BYTE[imageSize];
//Determine the up/down and left/right ordering of the pixels
BOOL bTopToBottom = (((fileHeader.byImageDescriptor >> 4) & 1) != 0);
BOOL bLeftToRight = (((fileHeader.byImageDescriptor >> 5) & 1) != 0);
//Copy the DIB bits from the user buffer into the DIB
int nInBytesPerPel = fileHeader.byPixelDepth / 8;
for (int j=0; jbiBitCount != 24)
{
TRACE(_T("Only 16 million colors (24 bit) images can be saved as Targa!\n"));
::GlobalUnlock((HGLOBAL) hDib);
return FALSE;
}
if (lpBI->biCompression != BI_RGB)
{
TRACE(_T("RLE-compressed images can't be saved as Targa!\n"));
::GlobalUnlock((HGLOBAL) hDib);
return FALSE;
}
DWORD dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation
// Now calculate the size of the image
DWORD dwBmBitsSize; // Size of Bitmap Bits only
// It's not RLE, so size is Width (DWORD aligned) * Height
dwBmBitsSize = WIDTHBYTES(lpBI->biWidth*((DWORD)lpBI->biBitCount)) * lpBI->biHeight;
dwDIBSize += dwBmBitsSize;
// Now, since we have calculated the correct size, why don't we
// fill in the biSizeImage field (this will fix any .BMP files which
// have this field incorrect).
lpBI->biSizeImage = dwBmBitsSize;
TRY
{
//First write out the header
TGA_FILE_HEADER fileHeader;
ZeroMemory(&fileHeader, sizeof(TGA_FILE_HEADER));
fileHeader.byImageType = 2;
fileHeader.nImageWidth = (short) lpBI->biWidth;
fileHeader.nImageHeight = (short) lpBI->biHeight;
fileHeader.byPixelDepth = 24;
file.SeekToBegin();
file.Write(&fileHeader, sizeof(TGA_FILE_HEADER));
//Allocate some memory to save the Dib bits into
BYTE* pImageData = (BYTE*)lpBI + lpBI->biSize;
DWORD dwImageDataSize = lpBI->biWidth*lpBI->biHeight*3;
BYTE* pBmp = new BYTE[dwImageDataSize];
//Copy the Dib bits into the buffer we just allocated
for (int j=0; jbiHeight; j++)
{
int nDepthOffset = j*WIDTHBYTES(lpBI->biWidth*24);
for (int i=0; ibiWidth; i++)
{
int nOutputOffset = j*lpBI->biWidth*3 + i*3;
int nInputOffset = nDepthOffset + i*3;
pBmp[nOutputOffset] = pImageData[nInputOffset];
pBmp[nOutputOffset+1] = pImageData[nInputOffset+1];
pBmp[nOutputOffset+2] = pImageData[nInputOffset+2];
}
}
::GlobalUnlock((HGLOBAL)hDib);
//Write the image data to disk
file.Write(pBmp, dwImageDataSize);
//Free up the memory we used
delete [] pBmp;
}
CATCH_ALL(e)
{
bSuccess = FALSE;
TRACE(_T("Error storing TGA file!\n"));
}
END_CATCH_ALL
return bSuccess;
}