// FIXME: assumes that we don't need to do gamma correction. bool Write( unsigned char *pImageData, const char *fileName, int width, int height, enum ImageFormat srcFormat, enum ImageFormat dstFormat ) { TGAHeader_t header; int x, y; // FIXME: need to handle conversion here. if( srcFormat != dstFormat ) { return false; } #ifdef TGAWRITER_USE_FOPEN FILE *fp; fp = fopen( fileName, "wb" ); if( !fp ) { return false; } #else assert( s_pFileSystem ); if( !s_pFileSystem ) { return false; } FileHandle_t fp; fp = s_pFileSystem->Open( fileName, "wb" ); #endif header.id_length = 0; // comment length header.colormap_type = 0; // ??? // Brian?: FIXME: should use BGR, etc, so that we can just fwrite the data. // Gary: TGA doesn't support BGR. switch( dstFormat ) { case IMAGE_FORMAT_RGB888: header.image_type = 2; // 24/32 bit uncompressed TGA header.pixel_size = 24; break; case IMAGE_FORMAT_RGBA8888: 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: #ifdef TGAWRITER_USE_FOPEN fclose( fp ); #else s_pFileSystem->Close( fp ); #endif return false; break; } header.colormap_index = 0; header.colormap_length = 0; header.colormap_size = 0; // can I flip this so that I can write the image out directly? header.x_origin = 0; header.y_origin = 0; header.width = ( unsigned short )width; header.height = ( unsigned short )height; header.attributes = 0; fputc( header.id_length, fp ); fputc( header.colormap_type, fp ); fputc( header.image_type, fp ); fputLittleShort( header.colormap_index, fp ); fputLittleShort( header.colormap_length, fp ); fputc( header.colormap_size, fp ); fputLittleShort( header.x_origin, fp ); fputLittleShort( header.y_origin, fp ); fputLittleShort( header.width, fp ); fputLittleShort( header.height, fp ); fputc( header.pixel_size, fp ); fputc( header.attributes, fp ); unsigned char *pbuf = (unsigned char *)_alloca( width * 4 ); switch( dstFormat ) { case IMAGE_FORMAT_RGB888: for( y = height - 1; y >= 0; y-- ) { int start = y * width * 3; int out = 0; for( x = 0; x < width; x++ ) { pbuf[out++] = pImageData[start + 2]; pbuf[out++] = pImageData[start + 1]; pbuf[out++] = pImageData[start + 0]; start += 3; } fwrite( pbuf, width, 3, fp ); // write a line } break; case IMAGE_FORMAT_RGBA8888: for( y = height - 1; y >= 0; y-- ) { int start = y * width * 4; int out = 0; for( x = 0; x < width; x++ ) { pbuf[out++] = pImageData[start + 2]; pbuf[out++] = pImageData[start + 1]; pbuf[out++] = pImageData[start + 0]; pbuf[out++] = pImageData[start + 3]; start += 4; } fwrite( pbuf, width, 4, fp ); // write a line } break; // FIXME: some programs don't understand our I8 files. . probably need to put // a linear ramp palette in the file. case IMAGE_FORMAT_I8: for( y = height - 1; y >= 0; y-- ) { fwrite( &pImageData[ y * width ], width, 1, fp ); } break; default: #ifdef TGAWRITER_USE_FOPEN fclose( fp ); #else s_pFileSystem->Close( fp ); #endif return false; break; } #ifdef TGAWRITER_USE_FOPEN fclose( fp ); #else s_pFileSystem->Close( fp ); #endif return true; }
//----------------------------------------------------------------------------- // 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; }