diff options
Diffstat (limited to 'vgui2/src/fileimage.cpp')
| -rw-r--r-- | vgui2/src/fileimage.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/vgui2/src/fileimage.cpp b/vgui2/src/fileimage.cpp new file mode 100644 index 0000000..b28c50a --- /dev/null +++ b/vgui2/src/fileimage.cpp @@ -0,0 +1,211 @@ +//========= Copyright 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); + } + } +} + + |