Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

212 lines
4.2 KiB

5 years ago
//========= 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);
}
}
}