//See http://www.paulbourke.net/dataformats/tga/ for TGA specification #include #include #include #include const int IMAGE_TYPE_RGB= 2; typedef unsigned char uchar; //Unmapped RGB(A) typedef struct { uchar idLength; // Number of Characters in Identification Field = the size of TGA header, 0 by default uchar colorMapType; // Color Map Type. 0 means no color map is included uchar imageType; // IMAGE_TYPE_RGB uchar colorMapSpec[5]; // ignored in case of Unmapped RGB image uint16_t xOrigin; // Image X origin - Integer ( lo-hi ) Y coordinate of the lower left corner of the image uint16_t yOrigin; // Image Y origin - Integer ( lo-hi ) Y coordinate of the lower left corner of the image uint16_t width; // Image width uint16_t height; // Image height uchar BPP; // Bits Per Pixel uchar imageDescriptor; // Image descriptor } TGAHeader; typedef struct { TGAHeader header; uchar* data; } TGAImage; size_t getNumberOfBytes(const TGAHeader& header) { return (size_t)header.width * (size_t)header.height * (header.BPP / 8); } void tgaSetHeader(TGAHeader& header, const uint16_t width, const uint16_t height) { memset(&header, 0, sizeof(TGAHeader)); header.idLength = 0; header.colorMapType = 0; header.imageType = IMAGE_TYPE_RGB; header.width = width; header.height = height; header.BPP = 32; header.imageDescriptor = 8; //BITS: 0 0 non-interleaved | 0 lower left origin | 0 reserved | 1 0 0 0 for Targa32 } void tgaAllocateData(uchar*& data, const TGAHeader& header) { data = (uchar*)malloc(getNumberOfBytes(header)); } TGAImage* tgaCreate(const uint16_t width, const uint16_t height ) { TGAImage * img = NULL; img = (TGAImage*)malloc(sizeof(TGAImage)); tgaSetHeader(img->header, width, height); tgaAllocateData(img->data, img->header); return img; } void tgaFree(TGAImage* img) { if (img) { free(img->data); free(img); img = NULL; } } void tgaZeros(TGAImage* img) { memset(img->data, 0, getNumberOfBytes(img->header)); } void tgaDrawWhiteRect(TGAImage* img, const int start_x, const int start_y, const int end_x, const int end_y ) { uchar* rgba = NULL; const int width = (int)img->header.width; const int bytesPerPixel = (int)(img->header.BPP / 8); for (int y = start_y; y < end_y; y++) { for (int x = start_x; x < end_x; x++) { rgba = &img->data[(y * width + x) * bytesPerPixel]; *rgba = 0xff; rgba++; *rgba = 0xff; rgba++; *rgba = 0xff; rgba++; *rgba = 0xff; } } } void tgaSave(const TGAImage* img, const char * filename ) { FILE* f = fopen( filename, "wb"); fwrite( &img->header, sizeof(TGAHeader), 1, f); //BEWARE OF struct ALIGNMENT !!!! This Should be 18 bytes !!!! :-) fwrite( img->data, getNumberOfBytes(img->header), 1, f); fflush(f); fclose(f); } int main() { const uint16_t width = 640; const uint16_t height = 480; printf("%d\n", sizeof(TGAHeader)); TGAImage* img = tgaCreate(width, height); tgaZeros(img); tgaDrawWhiteRect(img, 0, 0, 320, 240); tgaSave(img, "img.tga"); tgaFree(img); return 0; }