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