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.
279 lines
6.4 KiB
279 lines
6.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//============================================================================= |
|
|
|
#include "tgaloader.h" |
|
#include "tier0/dbg.h" |
|
|
|
#pragma pack(1) |
|
typedef struct _TargaHeader { |
|
unsigned char id_length, colormap_type, image_type; |
|
unsigned short colormap_index, colormap_length; |
|
unsigned char colormap_size; |
|
unsigned short x_origin, y_origin, width, height; |
|
unsigned char pixel_size, attributes; |
|
} TargaHeader; |
|
#pragma pack() |
|
|
|
#define TGA_ATTRIBUTE_HFLIP 16 |
|
#define TGA_ATTRIBUTE_VFLIP 32 |
|
|
|
|
|
int fgetLittleShort (unsigned char **p) |
|
{ |
|
byte b1, b2; |
|
|
|
b1 = *((*p)++); |
|
b2 = *((*p)++); |
|
|
|
return (short)(b1 + b2*256); |
|
} |
|
|
|
int fgetLittleLong (unsigned char **p) |
|
{ |
|
byte b1, b2, b3, b4; |
|
|
|
b1 = *((*p)++); |
|
b2 = *((*p)++); |
|
b3 = *((*p)++); |
|
b4 = *((*p)++); |
|
|
|
return b1 + (b2<<8) + (b3<<16) + (b4<<24); |
|
} |
|
|
|
|
|
bool GetTGADimensions( int32 iBytes, char *pData, int * width, int *height ) |
|
{ |
|
TargaHeader header; |
|
unsigned char *p = (unsigned char *)pData; |
|
if (width) *width = 0; |
|
if (height) *height = 0; |
|
|
|
header.id_length = *(p++); |
|
header.colormap_type = *(p++); |
|
header.image_type = *(p++); |
|
|
|
header.colormap_index = fgetLittleShort(&p); |
|
header.colormap_length = fgetLittleShort(&p); |
|
header.colormap_size = *(p++); |
|
header.x_origin = fgetLittleShort(&p); |
|
header.y_origin = fgetLittleShort(&p); |
|
header.width = fgetLittleShort(&p); |
|
header.height = fgetLittleShort(&p); |
|
header.pixel_size = *(p++); |
|
header.attributes = *(p++); |
|
|
|
if ( header.image_type != 2 && header.image_type != 10 ) |
|
{ |
|
Msg( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" ); |
|
return false; |
|
} |
|
|
|
if ( header.colormap_type !=0 || ( header.pixel_size != 32 && header.pixel_size != 24 ) ) |
|
{ |
|
Msg("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); |
|
return false; |
|
} |
|
|
|
if (width) *width = header.width; |
|
if (height) *height = header.height; |
|
return true; |
|
} |
|
|
|
|
|
bool LoadTGA( int32 iBytes, char *pData, byte **rawImage, int * rawImageBytes, int * width, int *height ) |
|
{ |
|
TargaHeader header; |
|
unsigned char *p = (unsigned char *)pData; |
|
if (width) *width = 0; |
|
if (height) *height = 0; |
|
|
|
header.id_length = *(p++); |
|
header.colormap_type = *(p++); |
|
header.image_type = *(p++); |
|
|
|
header.colormap_index = fgetLittleShort(&p); |
|
header.colormap_length = fgetLittleShort(&p); |
|
header.colormap_size = *(p++); |
|
header.x_origin = fgetLittleShort(&p); |
|
header.y_origin = fgetLittleShort(&p); |
|
header.width = fgetLittleShort(&p); |
|
header.height = fgetLittleShort(&p); |
|
header.pixel_size = *(p++); |
|
header.attributes = *(p++); |
|
|
|
if ( header.image_type != 2 && header.image_type != 10 ) |
|
{ |
|
Msg( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" ); |
|
return false; |
|
} |
|
|
|
if ( header.colormap_type !=0 || ( header.pixel_size != 32 && header.pixel_size != 24 ) ) |
|
{ |
|
Msg("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n"); |
|
return false; |
|
} |
|
|
|
int columns = header.width; |
|
int rows = header.height; |
|
int numPixels = columns * rows; |
|
|
|
if (width) *width = header.width; |
|
if (height) *height = header.height; |
|
if (rawImageBytes) *rawImageBytes = header.width * header.height * 4; |
|
|
|
*rawImage = new byte[ numPixels * 4 ]; |
|
byte *pixbuf = *rawImage; |
|
|
|
if ( header.id_length != 0 ) |
|
p += header.id_length; // skip TARGA image comment. |
|
|
|
if ( header.image_type == 2 ) { // Uncompressed, RGB images |
|
for(int row = rows - 1; row >=0; row-- ) |
|
{ |
|
if ( header.attributes & TGA_ATTRIBUTE_VFLIP ) |
|
pixbuf = *rawImage + (rows-row-1)*columns*4; |
|
else |
|
pixbuf = *rawImage + row*columns*4; |
|
|
|
for(int column=0; column < columns; column++) |
|
{ |
|
unsigned char red,green,blue,alphabyte; |
|
switch ( header.pixel_size ) |
|
{ |
|
case 24: |
|
|
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
*pixbuf++ = red; |
|
*pixbuf++ = green; |
|
*pixbuf++ = blue; |
|
*pixbuf++ = 255; |
|
break; |
|
case 32: |
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
alphabyte = *(p++); |
|
*pixbuf++ = red; |
|
*pixbuf++ = green; |
|
*pixbuf++ = blue; |
|
*pixbuf++ = alphabyte; |
|
break; |
|
} |
|
} |
|
} |
|
} |
|
else if ( header.image_type == 10 ) |
|
{ |
|
// Runlength encoded RGB images |
|
unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j; |
|
for( int row = rows - 1; row >= 0; row--) |
|
{ |
|
if ( header.attributes & TGA_ATTRIBUTE_VFLIP ) |
|
pixbuf = *rawImage + (rows-row-1)*columns*4; |
|
else |
|
pixbuf = *rawImage + row*columns*4; |
|
|
|
for( int column=0; column < columns; ) { |
|
packetHeader=*(p++); |
|
packetSize = 1 + (packetHeader & 0x7f); |
|
if (packetHeader & 0x80) { // run-length packet |
|
switch ( header.pixel_size ) |
|
{ |
|
case 24: |
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
alphabyte = 255; |
|
break; |
|
case 32: |
|
default: |
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
alphabyte = *(p++); |
|
break; |
|
} |
|
|
|
for(j=0;j<packetSize;j++) |
|
{ |
|
*pixbuf++=red; |
|
*pixbuf++=green; |
|
*pixbuf++=blue; |
|
*pixbuf++=alphabyte; |
|
column++; |
|
if (column==columns) { // run spans across rows |
|
column=0; |
|
if (row>0) |
|
row--; |
|
else |
|
goto breakOut; |
|
pixbuf = *rawImage + row*columns*4; |
|
} |
|
} |
|
} |
|
else |
|
{ // non run-length packet |
|
for(j=0;j<packetSize;j++) { |
|
switch (header.pixel_size) { |
|
case 24: |
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
*pixbuf++ = red; |
|
*pixbuf++ = green; |
|
*pixbuf++ = blue; |
|
*pixbuf++ = 255; |
|
break; |
|
case 32: |
|
blue = *(p++); |
|
green = *(p++); |
|
red = *(p++); |
|
alphabyte = *(p++); |
|
*pixbuf++ = red; |
|
*pixbuf++ = green; |
|
*pixbuf++ = blue; |
|
*pixbuf++ = alphabyte; |
|
break; |
|
} |
|
column++; |
|
if (column==columns) |
|
{ // pixel packet run spans across rows |
|
column=0; |
|
if (row>0) |
|
row--; |
|
else |
|
goto breakOut; |
|
pixbuf = *rawImage + row*columns*4; |
|
} |
|
} |
|
} |
|
} |
|
breakOut:; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void WriteTGA( const char *pchFileName, void *rgba, int wide, int tall ) |
|
{ |
|
_TargaHeader header; |
|
memset( &header, 0x0, sizeof(header) ); |
|
header.width = wide; |
|
header.height = tall; |
|
header.image_type = 2; |
|
header.pixel_size = 32; |
|
|
|
FILE *fp = fopen( pchFileName, "w+" ); |
|
fwrite( &header, 1, sizeof(header), fp ); |
|
fwrite( rgba, 1, wide*tall*4, fp ); |
|
fclose(fp); |
|
|
|
} |
|
|
|
|
|
|