|
|
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include <string.h>
#include "fileimage.h"
#include "winlite.h"
#include "vgui_internal.h"
#include "filesystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// TGA header.
#pragma pack(1)
class TGAFileHeader { public: unsigned char m_IDLength; unsigned char m_ColorMapType; unsigned char m_ImageType; unsigned short m_CMapStart; unsigned short m_CMapLength; unsigned char m_CMapDepth; unsigned short m_XOffset; unsigned short m_YOffset; unsigned short m_Width; unsigned short m_Height; unsigned char m_PixelDepth; unsigned char m_ImageDescriptor; }; #pragma pack()
// ---------------------------------------------------------------------------------------- //
// FileImageStream_Memory.
// ---------------------------------------------------------------------------------------- //
FileImageStream_Memory::FileImageStream_Memory(void *pData, int dataLen) { m_pData = (unsigned char*)pData; m_DataLen = dataLen; m_CurPos = 0; m_bError = false; }
void FileImageStream_Memory::Read(void *pData, int len) { unsigned char *pOut; int i;
pOut = (unsigned char*)pData; for(i=0; i < len; i++) { if(m_CurPos < m_DataLen) { pOut[i] = m_pData[m_CurPos]; ++m_CurPos; } else { pOut[i] = 0; m_bError = true; } } }
bool FileImageStream_Memory::ErrorStatus() { bool ret=m_bError; m_bError=false; return ret; }
// ---------------------------------------------------------------------------------------- //
// Encode/decode functions.
// ---------------------------------------------------------------------------------------- //
static void WriteRun(unsigned char *pColor, FileHandle_t fp, int runLength) { unsigned char runCount;
runCount = runLength - 1; runCount |= (1 << 7); g_pFullFileSystem->Write( &runCount, 1, fp ); g_pFullFileSystem->Write( pColor, 4, fp ); }
// Load in a 32-bit TGA file.
bool Load32BitTGA( FileImageStream *fp, FileImage *pImage) { TGAFileHeader hdr; char dummyChar; int i, x, y; long color; int runLength, curOut; unsigned char *pLine; unsigned char packetHeader;
pImage->Term();
// Read and verify the header.
fp->Read(&hdr, sizeof(hdr)); if(hdr.m_PixelDepth != 32 || hdr.m_ImageType != 10) return false;
// Skip the ID area..
for(i=0; i < hdr.m_IDLength; i++) fp->Read(&dummyChar, 1);
pImage->m_Width = hdr.m_Width; pImage->m_Height = hdr.m_Height; pImage->m_pData = new unsigned char[hdr.m_Width * hdr.m_Height * 4]; if(!pImage->m_pData) return false;
// Read in the data..
for(y=pImage->m_Height-1; y >= 0; y--) { pLine = &pImage->m_pData[y*pImage->m_Width*4];
curOut = 0; while(curOut < pImage->m_Width) { fp->Read(&packetHeader, 1); runLength = (int)(packetHeader & ~(1 << 7)) + 1; if(curOut + runLength > pImage->m_Width) return false;
if(packetHeader & (1 << 7)) { fp->Read(&color, 4); for(x=0; x < runLength; x++) { *((long*)pLine) = color; pLine += 4; } } else { for(x=0; x < runLength; x++) { fp->Read(&color, 4); *((long*)pLine) = color; pLine += 4; } }
curOut += runLength; } }
return true; }
// Write a 32-bit TGA file.
void Save32BitTGA( FileHandle_t fp, FileImage *pImage) { TGAFileHeader hdr; int y, runStart, x; unsigned char *pLine;
memset(&hdr, 0, sizeof(hdr)); hdr.m_PixelDepth = 32; hdr.m_ImageType = 10; // Run-length encoded RGB.
hdr.m_Width = pImage->m_Width; hdr.m_Height = pImage->m_Height;
g_pFullFileSystem->Write(&hdr, sizeof(hdr), fp ); // Lines are written bottom-up.
for(y=pImage->m_Height-1; y >= 0; y--) { pLine = &pImage->m_pData[y*pImage->m_Width*4]; runStart = 0; for(x=0; x < pImage->m_Width; x++) { if((x - runStart) >= 128 || *((long*)&pLine[runStart*4]) != *((long*)&pLine[x*4])) { // Encode this Run.
WriteRun(&pLine[runStart*4], fp, x - runStart); runStart = x; } }
// Encode the last Run.
if(x - runStart > 0) { WriteRun(&pLine[runStart*4], fp, x - runStart); } } }
|