// ================================================================ // $Id: tgaimg.h,v 1.2 2005/11/30 15:32:51 havran Exp $ // // tgaimg.h // // The definition of image in TGA format - interior representation if float // // REPLACEMENT_STRING // // Eurographics'04 submission, paper1292 // This source code should not be distributed unless accepted for publication. // #ifndef __TGAIMG_H__ #define __TGAIMG_H__ // ----------------------------------------------------------------------------- // The TGA image class class CTGAImage { /* Sun raster file header */ int _width, _height; float *_buf; float *_maxAdr; float *_adr; enum {CHANNELS = 3}; inline void ComputeAdr(int x, int y) { assert( (x>=0) && (x<_width)); assert( (y>=0) && (y<_height)); _adr = _buf + CHANNELS * (y*_width + x); assert(_adr < _maxAdr); } public: // constructor and destructor CTGAImage() { _width = _height = 0; _buf = NULL;} ~CTGAImage() { CleanUp(); } void CleanUp() { delete []_buf; _buf = 0; _maxAdr = 0;} int GetWidth() const { return _width;} int GetHeight() const { return _height;} void Init(int width, int height) { assert(width > 0); assert(height > 0); _width = width; _height = height; _buf = new float[_width * _height * CHANNELS]; _maxAdr = &_buf[_width * _height * CHANNELS]; assert(_buf); // make the image black memset(_buf, 0, _width * _height * CHANNELS * sizeof(float)); } void FillInImage(float r, float g, float b) { for (int y = 0; y < _height; y++) { for (int x = 0; x < _width; x++) { ComputeAdr(x,y); *_adr = r; _adr++; *_adr = g; _adr++; *_adr = b; } // for x } // for y } void SetPixel(int x, int y, float r, float g, float b) { ComputeAdr(x,y); *_adr = r; _adr++; *_adr = g; _adr++; *_adr = b; } void SetPixelClip(int x, int y, float r, float g, float b) { if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) return; ComputeAdr(x,y); *_adr = r; _adr++; *_adr = g; _adr++; *_adr = b; } void GetPixel(int x, int y, float &r, float &g, float &b) { ComputeAdr(x,y); r = *_adr; _adr++; g = *_adr; _adr++; b = *_adr; } // save to a file of a given name - return 0 on success int SaveToFile(const char *filename); }; inline int CTGAImage::SaveToFile(const char *filename) { int i, j; int channelNum = CHANNELS; int width = _width; int height = _height; // Only 3 or 4 channels in file are supported if (channelNum != 3 && channelNum != 4) { cerr << "Invalid number of channels: " << channelNum << '\n'; cerr << "Only 3 or 4 channels in file are supported\n"; return 1; // error } FILE *f = fopen(filename,"wb"); if (!f) return 1; // file cannot be opened printf("Saving image (%d x %d) to a file %s \n", width, height, filename); fprintf(f,"%c", 0); // CImage ID length (no image ID = 0) fprintf(f,"%c", 0); // Colormap type (no colormap = 0) fprintf(f,"%c", 2); // CImage type (uncompressed true-color = 2) // Color Map specification (0 - no colormap) fprintf(f,"%c%c%c%c%c",0,0,0,0,0); fprintf(f,"%c%c", 0, 0); // X image origin (0 - no offset) fprintf(f,"%c%c", 0, 0); // Y image origin (0 - no offset) // CImage width fprintf(f,"%c%c", ((unsigned char)(width >> 0)), ((unsigned char)(width >> 8))); // CImage height fprintf(f,"%c%c", ((unsigned char)(height >> 0)), ((unsigned char)(height >> 8))); // Pixel depth (24 or 32 bpp: true-color) fprintf(f,"%c", (channelNum * 8)); if (channelNum == 4) // CImage descriptor fprintf(f,"%c", 0x28); // 0010X000 - 00 - unused else // 10 - left-to-right,top-to-bottom fprintf(f,"%c", 0x20); // 0000 or 1000 - no alpha or // 1 byte of alpha // CImage ID not used // CImage colormap not used // CImage data follows (RGB triplets) fflush(f); for (j = 0; j < height; j++){ for (i = 0; i < width; i++) { ComputeAdr(i, j); unsigned char val; float r,g,b; r = *_adr; _adr++; g = *_adr; _adr++; b = *_adr; if (channelNum >= 3) { if (b > 255.f) b = 255.f; val = (unsigned char) b; // Blue fprintf(f,"%c", val); // Blue } if (channelNum >= 2) { if (g > 255.f) g = 255.f; val = (unsigned char) g; // Green fprintf(f,"%c", val); // Green } if (channelNum >= 1) { if (r > 255.f) r = 255.f; val = (unsigned char) r; // Red fprintf(f,"%c", val); // Red } if (channelNum == 4) { _adr++; // alpha value should be in range 0.0-1.0 float a = *_adr; fprintf(f,"%c", (unsigned char)(255.0 * a)); // Alpha } } } fflush(f); fprintf(f,"%c%c%c%c",0,0,0,0); // no extension area - offset = 0 fprintf(f,"%c%c%c%c",0,0,0,0); // no developers directory - offset = 0 fprintf(f,"TRUEVISION-XFILE."); // new TGA signature fclose(f); return 0; // ok } #endif // __TGAIMG_H__