diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /bitmap/tgawriter.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'bitmap/tgawriter.cpp')
| -rw-r--r-- | bitmap/tgawriter.cpp | 353 |
1 files changed, 353 insertions, 0 deletions
diff --git a/bitmap/tgawriter.cpp b/bitmap/tgawriter.cpp new file mode 100644 index 0000000..a73c996 --- /dev/null +++ b/bitmap/tgawriter.cpp @@ -0,0 +1,353 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#include <stdlib.h> +#include <stdio.h> +#include "tier0/dbg.h" +#include <malloc.h> +#include "filesystem.h" +#include "bitmap/tgawriter.h" +#include "tier1/utlbuffer.h" +#include "bitmap/imageformat.h" +#include "tier2/tier2.h" +#include "tier2/fileutils.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +namespace TGAWriter +{ + +#pragma pack(1) +struct TGAHeader_t +{ + unsigned char id_length; + unsigned char colormap_type; + unsigned char image_type; + unsigned short colormap_index; + unsigned short colormap_length; + unsigned char colormap_size; + unsigned short x_origin; + unsigned short y_origin; + unsigned short width; + unsigned short height; + unsigned char pixel_size; + unsigned char attributes; +}; +#pragma pack() + +#define fputc myfputc +#define fwrite myfwrite + +static void fputLittleShort( unsigned short s, CUtlBuffer &buffer ) +{ + buffer.PutChar( s & 0xff ); + buffer.PutChar( s >> 8 ); +} + +static inline void myfputc( unsigned char c, FileHandle_t fileHandle ) +{ + g_pFullFileSystem->Write( &c, 1, fileHandle ); +} + +static inline void myfwrite( void const *data, int size1, int size2, FileHandle_t fileHandle ) +{ + g_pFullFileSystem->Write( data, size1 * size2, fileHandle ); +} + + +//----------------------------------------------------------------------------- +// FIXME: assumes that we don't need to do gamma correction. +//----------------------------------------------------------------------------- +bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height, + ImageFormat srcFormat, ImageFormat dstFormat ) +{ + TGAHeader_t header; + + // Fix the dstFormat to match what actually is going to go into the file + switch( dstFormat ) + { + case IMAGE_FORMAT_RGB888: + dstFormat = IMAGE_FORMAT_BGR888; + break; +#if defined( _X360 ) + case IMAGE_FORMAT_LINEAR_RGB888: + dstFormat = IMAGE_FORMAT_LINEAR_BGR888; + break; +#endif + case IMAGE_FORMAT_RGBA8888: + dstFormat = IMAGE_FORMAT_BGRA8888; + break; + } + + header.id_length = 0; // comment length + header.colormap_type = 0; // ??? + + switch( dstFormat ) + { + case IMAGE_FORMAT_BGR888: +#if defined( _X360 ) + case IMAGE_FORMAT_LINEAR_BGR888: +#endif + header.image_type = 2; // 24/32 bit uncompressed TGA + header.pixel_size = 24; + break; + case IMAGE_FORMAT_BGRA8888: + header.image_type = 2; // 24/32 bit uncompressed TGA + header.pixel_size = 32; + break; + case IMAGE_FORMAT_I8: + header.image_type = 1; // 8 bit uncompressed TGA + header.pixel_size = 8; + break; + default: + return false; + break; + } + + header.colormap_index = 0; + header.colormap_length = 0; + header.colormap_size = 0; + header.x_origin = 0; + header.y_origin = 0; + header.width = ( unsigned short )width; + header.height = ( unsigned short )height; + header.attributes = 0x20; // Makes it so we don't have to vertically flip the image + + buffer.PutChar( header.id_length ); + buffer.PutChar( header.colormap_type ); + buffer.PutChar( header.image_type ); + fputLittleShort( header.colormap_index, buffer ); + fputLittleShort( header.colormap_length, buffer ); + buffer.PutChar( header.colormap_size ); + fputLittleShort( header.x_origin, buffer ); + fputLittleShort( header.y_origin, buffer ); + fputLittleShort( header.width, buffer ); + fputLittleShort( header.height, buffer ); + buffer.PutChar( header.pixel_size ); + buffer.PutChar( header.attributes ); + + int nSizeInBytes = width * height * ImageLoader::SizeInBytes( dstFormat ); + buffer.EnsureCapacity( buffer.TellPut() + nSizeInBytes ); + unsigned char *pDst = (unsigned char*)buffer.PeekPut(); + + if ( !ImageLoader::ConvertImageFormat( pImageData, srcFormat, pDst, dstFormat, width, height ) ) + return false; + + buffer.SeekPut( CUtlBuffer::SEEK_CURRENT, nSizeInBytes ); + return true; +} + +bool WriteDummyFileNoAlloc( const char *fileName, int width, int height, enum ImageFormat dstFormat ) +{ + TGAHeader_t tgaHeader; + + Assert( g_pFullFileSystem ); + if( !g_pFullFileSystem ) + { + return false; + } + COutputFile fp( fileName ); + + int nBytesPerPixel, nImageType, nPixelSize; + + switch( dstFormat ) + { + case IMAGE_FORMAT_BGR888: +#if defined( _X360 ) + case IMAGE_FORMAT_LINEAR_BGR888: +#endif + nBytesPerPixel = 3; // 24/32 bit uncompressed TGA + nPixelSize = 24; + nImageType = 2; + break; + case IMAGE_FORMAT_BGRA8888: + nBytesPerPixel = 4; // 24/32 bit uncompressed TGA + nPixelSize = 32; + nImageType = 2; + break; + case IMAGE_FORMAT_I8: + nBytesPerPixel = 1; // 8 bit uncompressed TGA + nPixelSize = 8; + nImageType = 1; + break; + default: + return false; + break; + } + + memset( &tgaHeader, 0, sizeof(tgaHeader) ); + tgaHeader.id_length = 0; + tgaHeader.image_type = (unsigned char) nImageType; + tgaHeader.width = (unsigned short) width; + tgaHeader.height = (unsigned short) height; + tgaHeader.pixel_size = (unsigned char) nPixelSize; + tgaHeader.attributes = 0x20; + + // Write the Targa header + fp.Write( &tgaHeader, sizeof(TGAHeader_t) ); + + // Write out width * height black pixels + unsigned char black[4] = { 0x1E, 0x9A, 0xFF, 0x00 }; + for (int i = 0; i < width * height; i++) + { + fp.Write( black, nBytesPerPixel ); + } + + return true; +} + +bool WriteTGAFile( const char *fileName, int width, int height, enum ImageFormat srcFormat, uint8 const *srcData, int nStride ) +{ + TGAHeader_t tgaHeader; + + COutputFile fp( fileName ); + + int nBytesPerPixel, nImageType, nPixelSize; + + bool bMustConvert = false; + ImageFormat dstFormat = srcFormat; + + switch( srcFormat ) + { + case IMAGE_FORMAT_BGR888: +#if defined( _X360 ) + case IMAGE_FORMAT_LINEAR_BGR888: +#endif + nBytesPerPixel = 3; // 24/32 bit uncompressed TGA + nPixelSize = 24; + nImageType = 2; + break; + case IMAGE_FORMAT_BGRA8888: + nBytesPerPixel = 4; // 24/32 bit uncompressed TGA + nPixelSize = 32; + nImageType = 2; + break; + case IMAGE_FORMAT_RGBA8888: + bMustConvert = true; + dstFormat = IMAGE_FORMAT_BGRA8888; + nBytesPerPixel = 4; // 24/32 bit uncompressed TGA + nPixelSize = 32; + nImageType = 2; + break; + case IMAGE_FORMAT_I8: + nBytesPerPixel = 1; // 8 bit uncompressed TGA + nPixelSize = 8; + nImageType = 1; + break; + default: + return false; + break; + } + + memset( &tgaHeader, 0, sizeof(tgaHeader) ); + tgaHeader.id_length = 0; + tgaHeader.image_type = (unsigned char) nImageType; + tgaHeader.width = (unsigned short) width; + tgaHeader.height = (unsigned short) height; + tgaHeader.pixel_size = (unsigned char) nPixelSize; + tgaHeader.attributes = 0x20; + + // Write the Targa header + fp.Write( &tgaHeader, sizeof(TGAHeader_t) ); + + // Write out image data + if ( bMustConvert ) + { + uint8 *pLineBuf = new uint8[ nBytesPerPixel * width ]; + while( height-- ) + { + ImageLoader::ConvertImageFormat( srcData, srcFormat, pLineBuf, dstFormat, width, 1 ); + fp.Write( pLineBuf, nBytesPerPixel * width ); + srcData += nStride; + } + delete[] pLineBuf; + } + else + { + while( height-- ) + { + fp.Write( srcData, nBytesPerPixel * width ); + srcData += nStride; + } + + } + return true; +} + + +bool WriteRectNoAlloc( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nStride, enum ImageFormat srcFormat ) +{ + Assert( g_pFullFileSystem ); + if( !g_pFullFileSystem ) + { + return false; + } + FileHandle_t fp; + fp = g_pFullFileSystem->Open( fileName, "r+b" ); + + // + // Read in the targa header + // + TGAHeader_t tgaHeader; + g_pFullFileSystem->Read( &tgaHeader, sizeof(tgaHeader), fp ); + + + int nBytesPerPixel, nPixelSize; + + switch( srcFormat ) + { + case IMAGE_FORMAT_BGR888: +#if defined( _X360 ) + case IMAGE_FORMAT_LINEAR_BGR888: +#endif + nBytesPerPixel = 3; // 24/32 bit uncompressed TGA + nPixelSize = 24; + break; + case IMAGE_FORMAT_BGRA8888: + nBytesPerPixel = 4; // 24/32 bit uncompressed TGA + nPixelSize = 32; + break; + case IMAGE_FORMAT_I8: + nBytesPerPixel = 1; // 8 bit uncompressed TGA + nPixelSize = 8; + break; + default: + return false; + break; + } + + // Verify src data matches the targa we're going to write into + if ( nPixelSize != tgaHeader.pixel_size ) + { + Warning( "TGA doesn't match source data.\n" ); + return false; + } + + + // Seek to the origin of the target subrect from the beginning of the file + g_pFullFileSystem->Seek( fp, nBytesPerPixel * (tgaHeader.width * nYOrigin + nXOrigin), FILESYSTEM_SEEK_CURRENT ); + + unsigned char *pSrc = pImageData; + + // Run through each scanline of the incoming rect + for (int row=0; row < height; row++ ) + { + g_pFullFileSystem->Write( pSrc, nBytesPerPixel * width, fp ); + + // Advance src pointer to next scanline + pSrc += nBytesPerPixel * nStride; + + // Seek ahead in the file + g_pFullFileSystem->Seek( fp, nBytesPerPixel * ( tgaHeader.width - width ), FILESYSTEM_SEEK_CURRENT ); + } + + g_pFullFileSystem->Close( fp ); + return true; +} + +} // end namespace TGAWriter + |