读取TGA的代码
typedef unsigned char uchar_t
typedef unsigned short ushort_t
struct bgra_s {
union {
struct { uchar_t _b, _g, _r, _a; };
ulong_t _argb;
uchar_t _v[4];
};
// operators
bgra_s & operator= (const bgra_s & src)
{ _argb = src._argb; return *this; }
};
typedef bgra_s * bgra_p;
struct TGA_HEADER { // TGA file header
uchar_t id_length;
uchar_t colormap_type;
uchar_t image_type;
ushort_t colormap_index, colormap_length;
uchar_t colormap_size;
ushort_t x_origin, y_origin, width, height;
uchar_t pixel_size, attributes;
} ;
// tga : TGA格式的图象数据
// width : 返回图象的宽度
// height : 返回图象的高度
// 函数返回值 : 返回解压后的RGBA数据,返回0表示出错
bgra_s * TGA_decode(uchar_t *tga, long *width, long *height)
{
long columns, rows, numPixels;
long row, column;
bgra_s *rgba, *dest;
TGA_HEADER *header;
uchar_t red,green,blue,alpha,packetHeader,packetSize,j;
header = (TGA_HEADER *)tga;
tga+=sizeof(TGA_HEADER);
// Only types 2 and 10 are supported
if (header->image_type!=2 && header->image_type!=10) {
printf("TGA_decode() failed: unsupported tga compression type.\n");
return 0;
}
// Only 24bit or 32bit pixels are supported
if (header->colormap_type!=0||
(header->pixel_size!=32&&header->pixel_size!=24)) {
printf("TGA_decode() failed: only 24bit and 32bits image are supported\n");
return 0;
}
columns = header->width;
rows = header->height;
numPixels = columns * rows;
if (width) *width = columns;
if (height) *height = rows;
// Allocate memory for decoded image
rgba = (bgra_s*)malloc(numPixels * sizeof(bgra_s));
if (!rgba) {
printf("TGA_decode() failed: can not allocate memory of decoded image\n");
return 0;
}
// Skip comment
if (header->id_length!=0)
tga+=header->id_length;
// Uncompressed RGB image
__try
{
if (header->image_type==2) {
dest = rgba;
//for(row=rows-1; row>=0; row--) {
for(row=0; row < rows; ++row) {
// dest = rgba + row*columns*4;
for(column=0; column<columns; ++column) {
if (header->pixel_size==24) {
dest->_b = *tga; ++tga;
dest->_g = *tga; ++tga;
dest->_r = *tga; ++tga;
dest->_a = 255;
}
else if (header->pixel_size==32) {
dest->_b = *tga; ++tga;
dest->_g = *tga; ++tga;
dest->_r = *tga; ++tga;
dest->_a = *tga; ++tga;
}
++dest;
}
}
}
// RLE RGB image
else if (header->image_type==10) {
for(row=rows-1; row>=0; row--) {
dest = bgra_p((uchar_t*)rgba + row*columns*4);
for(column=0; column<columns; ) {
packetHeader=*tga; tga++;
packetSize = 1 + (packetHeader & 0x7f);
// RLE packet
if (packetHeader & 0x80) {
if (header->pixel_size==24) {
blue = *tga; tga++;
green = *tga; tga++;
red = *tga; tga++;
alpha = 255;
}
else if (header->pixel_size==32) {
blue = *tga; tga++;
green = *tga; tga++;
red = *tga; tga++;
alpha = *tga; tga++;
}
for(j=0;j<packetSize;j++) {
dest->_r = red;
dest->_g = green;
dest->_b = blue;
dest->_a = alpha;
++dest;
++column;
if (column==columns) {
column=0;
if (row>0)
row--;
else
goto end_decode;
dest = bgra_p((uchar_t*)rgba + row*columns*4);
}
}
}
// Non-RLE packet
else {
for(j=0;j<packetSize;j++) {
if (header->pixel_size==24) {
dest->_b = *tga; ++tga;
dest->_g = *tga; ++tga;
dest->_r = *tga; ++tga;
dest->_a = 255;
}
else if (header->pixel_size==32) {
dest->_b = *tga; ++tga;
dest->_g = *tga; ++tga;
dest->_r = *tga; ++tga;
dest->_a = *tga; ++tga;
}
++dest;
column++;
if (column==columns) {
column=0;
if (row>0)
row--;
else
goto end_decode;
dest = bgra_p((uchar_t*)rgba + row*columns*4);
}
}
}
}
end_decode:;
}
}
} // end of __try block
// except handler
__except(1)
{
printf("TGA_decode() failed: system exception!\n");
free(rgba);
return 0;
}
// normal exit
return(rgba);
}