|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "tga.h" |
|
|
#include "core.h" |
|
|
#include "types.h" |
|
|
|
|
|
#include <stdio.h> |
|
|
#include <string.h> |
|
|
|
|
|
using namespace std; |
|
|
|
|
|
struct TgaHeader |
|
|
{ |
|
|
uint8_t identsize; |
|
|
uint8_t colourmaptype; |
|
|
uint8_t imagetype; |
|
|
|
|
|
uint16_t colourmapstart; |
|
|
uint16_t colourmaplength; |
|
|
uint8_t colourmapbits; |
|
|
|
|
|
uint16_t xstart; |
|
|
uint16_t ystart; |
|
|
uint16_t width; |
|
|
uint16_t height; |
|
|
uint8_t bits; |
|
|
uint8_t descriptor; |
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
namespace |
|
|
{ |
|
|
|
|
|
void memwrite(void* src, uint32_t size, unsigned char*& buffer) |
|
|
{ |
|
|
memcpy(buffer, src, size); |
|
|
buffer += size; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool TgaSave(const char* filename, const TgaImage& image, bool rle) |
|
|
{ |
|
|
FILE* f = fopen(filename, "wb"); |
|
|
if (f) |
|
|
{ |
|
|
bool b = TgaSave(f, image, rle); |
|
|
fclose(f); |
|
|
|
|
|
return b; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
bool TgaSave(FILE* f, const TgaImage& image, bool rle) |
|
|
{ |
|
|
TgaHeader header; |
|
|
|
|
|
header.identsize = 0; |
|
|
header.colourmaptype = 0; |
|
|
header.imagetype = rle?9:2; |
|
|
header.colourmapstart = 0; |
|
|
header.colourmaplength = 0; |
|
|
header.colourmapbits = 0; |
|
|
header.xstart = 0; |
|
|
header.ystart = 0; |
|
|
header.width = image.m_width; |
|
|
header.height = image.m_height; |
|
|
header.bits = 32; |
|
|
header.descriptor = 0; |
|
|
|
|
|
if (f) |
|
|
{ |
|
|
unsigned char* data = (unsigned char*)new uint32_t[image.m_width*image.m_height + sizeof(header)]; |
|
|
unsigned char* writeptr = data; |
|
|
|
|
|
memwrite(&header.identsize, sizeof(header.identsize), writeptr); |
|
|
memwrite(&header.colourmaptype, sizeof(header.colourmaptype), writeptr); |
|
|
memwrite(&header.imagetype, sizeof(header.imagetype), writeptr); |
|
|
memwrite(&header.colourmapstart, sizeof(header.colourmapstart), writeptr); |
|
|
memwrite(&header.colourmaplength, sizeof(header.colourmaplength), writeptr); |
|
|
memwrite(&header.colourmapbits, sizeof(header.colourmapbits), writeptr); |
|
|
memwrite(&header.xstart, sizeof(header.xstart), writeptr); |
|
|
memwrite(&header.ystart, sizeof(header.ystart), writeptr); |
|
|
memwrite(&header.width, sizeof(header.width), writeptr); |
|
|
memwrite(&header.height, sizeof(header.height), writeptr); |
|
|
memwrite(&header.bits, sizeof(header.bits), writeptr); |
|
|
memwrite(&header.descriptor, sizeof(header.descriptor), writeptr); |
|
|
|
|
|
union texel |
|
|
{ |
|
|
uint32_t u32; |
|
|
uint8_t u8[4]; |
|
|
}; |
|
|
|
|
|
texel* t = (texel*)image.m_data; |
|
|
for (int i=0; i < image.m_width*image.m_height; ++i) |
|
|
{ |
|
|
texel tmp = t[i]; |
|
|
swap(tmp.u8[0], tmp.u8[2]); |
|
|
memwrite(&tmp.u32, 4, writeptr); |
|
|
} |
|
|
|
|
|
fwrite(data, writeptr-data, 1, f); |
|
|
|
|
|
|
|
|
delete[] data; |
|
|
|
|
|
return true; |
|
|
} |
|
|
else |
|
|
{ |
|
|
return false; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool TgaLoad(const char* filename, TgaImage& image) |
|
|
{ |
|
|
if (!filename) |
|
|
return false; |
|
|
|
|
|
FILE* aTGAFile = fopen(filename, "rb"); |
|
|
if (aTGAFile == NULL) |
|
|
{ |
|
|
printf("Texture: could not open %s for reading.\n", filename); |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
char aHeaderIDLen; |
|
|
size_t err; |
|
|
err = fread(&aHeaderIDLen, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
char aColorMapType; |
|
|
err = fread(&aColorMapType, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
char anImageType; |
|
|
err = fread(&anImageType, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
short aFirstEntryIdx; |
|
|
err = fread(&aFirstEntryIdx, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
short aColorMapLen; |
|
|
err = fread(&aColorMapLen, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
char aColorMapEntrySize; |
|
|
err = fread(&aColorMapEntrySize, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
short anXOrigin; |
|
|
err = fread(&anXOrigin, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
short aYOrigin; |
|
|
err = fread(&aYOrigin, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
short anImageWidth; |
|
|
err = fread(&anImageWidth, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
short anImageHeight; |
|
|
err = fread(&anImageHeight, sizeof(uint16_t), 1, aTGAFile); |
|
|
|
|
|
char aBitCount = 32; |
|
|
err = fread(&aBitCount, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
char anImageDescriptor; |
|
|
err = fread((char*)&anImageDescriptor, sizeof(uint8_t), 1, aTGAFile); |
|
|
|
|
|
|
|
|
(void)err; |
|
|
|
|
|
|
|
|
uint8_t numComponents = aBitCount / 8; |
|
|
uint32_t numTexels = anImageWidth * anImageHeight; |
|
|
|
|
|
|
|
|
image.m_width = anImageWidth; |
|
|
image.m_height = anImageHeight; |
|
|
image.m_data = new uint32_t[numTexels]; |
|
|
|
|
|
|
|
|
for (uint32_t i=0; i < numTexels; ++i) |
|
|
{ |
|
|
union texel |
|
|
{ |
|
|
uint32_t u32; |
|
|
uint8_t u8[4]; |
|
|
}; |
|
|
|
|
|
texel t; |
|
|
t.u32 = 0; |
|
|
|
|
|
if (!fread(&t.u32, numComponents, 1, aTGAFile)) |
|
|
{ |
|
|
printf("Texture: file not fully read, may be corrupt (%s)\n", filename); |
|
|
} |
|
|
|
|
|
|
|
|
swap(t.u8[0], t.u8[2]); |
|
|
|
|
|
|
|
|
image.m_data[i] = t.u32; |
|
|
} |
|
|
|
|
|
|
|
|
if (anImageDescriptor & (1 << 5)) |
|
|
{ |
|
|
|
|
|
|
|
|
int rowSize = image.m_width*4; |
|
|
|
|
|
uint8_t* buf = new uint8_t[image.m_width*4]; |
|
|
uint8_t* start = (uint8_t*)image.m_data; |
|
|
uint8_t* end = &((uint8_t*)image.m_data)[rowSize*(image.m_height-1)]; |
|
|
|
|
|
while (start < end) |
|
|
{ |
|
|
memcpy(buf, end, rowSize); |
|
|
memcpy(end, start, rowSize); |
|
|
memcpy(start, buf, rowSize); |
|
|
|
|
|
start += rowSize; |
|
|
end -= rowSize; |
|
|
} |
|
|
|
|
|
delete[] buf; |
|
|
} |
|
|
|
|
|
fclose(aTGAFile); |
|
|
|
|
|
return true; |
|
|
} |
|
|
|
|
|
void TgaFree(const TgaImage& image) |
|
|
{ |
|
|
delete[] image.m_data; |
|
|
} |
|
|
|