#pragma pack(push,1)
typedef struct {
unsigned char idLength;
unsigned char colormapType;
unsigned char imageType;
unsigned short colormapIndex;
unsigned short colormapLength;
unsigned char colormapSize;
unsigned short xOrigin;
unsigned short yOrigin;
unsigned short width;
unsigned short height;
unsigned char pixelSize;
unsigned char attributes;
} TgaHeader;
#pragma pack(pop)
int imageLoadTga(const char *path, int *outWidth, int *outHeight, unsigned char **pixels) {
*outWidth = *outHeight = 0; *pixels = NULL;
FILE *f = fopen(path, "rb");
if (!f) {
fprintf(stderr, "Cannot open for read: %s\n", path);
fflush(stderr);
return FALSE;
}
TgaHeader header = {};
fread(&header, sizeof(header), 1, f); // todo: endianess
//printf("%d %d %d %d %d\n", header.imageType, header.width, header.height, header.colormapType, header.pixelSize);
if ( header.imageType != 2
|| !header.width
|| !header.height
|| header.colormapType
|| (header.pixelSize != 24 && header.pixelSize != 32)
) {
fprintf(stderr, "Unsupported format. Only uncompressed 24 or 32 bits TGA are supported: %s\n", path);
fflush(stderr);
return FALSE;
}
fseek(f, header.idLength, SEEK_CUR);
*outWidth = header.width;
*outHeight = header.height;
int rowSize = *outWidth*4;
int size = *outHeight*rowSize;
*pixels = (unsigned char*)calloc(1, size);
unsigned char *row = *pixels + size;
for(unsigned short r = header.height; r; --r, row -= rowSize) {
for(unsigned char *c = row - rowSize; c < row; c += 4) {
c[2] = fgetc(f);
c[1] = fgetc(f);
c[0] = fgetc(f);
c[3] = header.pixelSize == 32 ? fgetc(f) : 255;
}
}
fclose(f);
return TRUE;
}
int imageSaveTga(const char *path, int width, int height, const unsigned char *pixels) {
if (width <= 0 || height <= 0 || !pixels) return FALSE;
FILE *f = fopen(path, "wb");
if (!f) {
fprintf(stderr, "Cannot open file for write: %s\n", path);
fflush(stderr);
return FALSE;
}
TgaHeader header = {};
header.imageType = 2;
header.width = width;
header.height = height;
header.pixelSize = 32;
fwrite(&header, sizeof(header), 1, f); // todo: endianess
int rowSize = width*4;
int size = height*rowSize;
const unsigned char *row = pixels + size;
for(unsigned short r = header.height; r; --r, row -= rowSize) {
for(const unsigned char *c = row - rowSize; c < row; c += 4) {
fputc(c[2], f);
fputc(c[1], f);
fputc(c[0], f);
fputc(c[3], f);
}
}
fclose(f);
return TRUE;
}