[2631] | 1 | // ================================================================
|
---|
| 2 | // $Id: tgaimg.h,v 1.2 2005/11/30 15:32:51 havran Exp $
|
---|
| 3 | //
|
---|
| 4 | // tgaimg.h
|
---|
| 5 | //
|
---|
| 6 | // The definition of image in TGA format - interior representation if float
|
---|
| 7 | //
|
---|
| 8 | // REPLACEMENT_STRING
|
---|
| 9 | //
|
---|
| 10 | // Eurographics'04 submission, paper1292
|
---|
| 11 | // This source code should not be distributed unless accepted for publication.
|
---|
| 12 | //
|
---|
| 13 |
|
---|
| 14 | #ifndef __TGAIMG_H__
|
---|
| 15 | #define __TGAIMG_H__
|
---|
| 16 |
|
---|
| 17 | // -----------------------------------------------------------------------------
|
---|
| 18 | // The TGA image class
|
---|
| 19 | class CTGAImage
|
---|
| 20 | { /* Sun raster file header */
|
---|
| 21 | int _width, _height;
|
---|
| 22 | float *_buf;
|
---|
| 23 | float *_maxAdr;
|
---|
| 24 | float *_adr;
|
---|
| 25 | enum {CHANNELS = 3};
|
---|
| 26 | inline void ComputeAdr(int x, int y) {
|
---|
| 27 | assert( (x>=0) && (x<_width));
|
---|
| 28 | assert( (y>=0) && (y<_height));
|
---|
| 29 | _adr = _buf + CHANNELS * (y*_width + x);
|
---|
| 30 | assert(_adr < _maxAdr);
|
---|
| 31 | }
|
---|
| 32 | public:
|
---|
| 33 | // constructor and destructor
|
---|
| 34 | CTGAImage() { _width = _height = 0; _buf = NULL;}
|
---|
| 35 | ~CTGAImage() { CleanUp(); }
|
---|
| 36 |
|
---|
| 37 | void CleanUp() { delete []_buf; _buf = 0; _maxAdr = 0;}
|
---|
| 38 |
|
---|
| 39 | int GetWidth() const { return _width;}
|
---|
| 40 | int GetHeight() const { return _height;}
|
---|
| 41 |
|
---|
| 42 | void Init(int width, int height) {
|
---|
| 43 | assert(width > 0);
|
---|
| 44 | assert(height > 0);
|
---|
| 45 | _width = width; _height = height;
|
---|
| 46 | _buf = new float[_width * _height * CHANNELS];
|
---|
| 47 | _maxAdr = &_buf[_width * _height * CHANNELS];
|
---|
| 48 | assert(_buf);
|
---|
| 49 | // make the image black
|
---|
| 50 | memset(_buf, 0, _width * _height * CHANNELS * sizeof(float));
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | void FillInImage(float r, float g, float b) {
|
---|
| 54 | for (int y = 0; y < _height; y++) {
|
---|
| 55 | for (int x = 0; x < _width; x++) {
|
---|
| 56 | ComputeAdr(x,y);
|
---|
| 57 | *_adr = r; _adr++;
|
---|
| 58 | *_adr = g; _adr++;
|
---|
| 59 | *_adr = b;
|
---|
| 60 | } // for x
|
---|
| 61 | } // for y
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | void SetPixel(int x, int y, float r, float g, float b) {
|
---|
| 65 | ComputeAdr(x,y);
|
---|
| 66 | *_adr = r; _adr++;
|
---|
| 67 | *_adr = g; _adr++;
|
---|
| 68 | *_adr = b;
|
---|
| 69 | }
|
---|
| 70 |
|
---|
| 71 | void SetPixelClip(int x, int y, float r, float g, float b) {
|
---|
| 72 | if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
|
---|
| 73 | return;
|
---|
| 74 | ComputeAdr(x,y);
|
---|
| 75 | *_adr = r; _adr++;
|
---|
| 76 | *_adr = g; _adr++;
|
---|
| 77 | *_adr = b;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | void GetPixel(int x, int y, float &r, float &g, float &b) {
|
---|
| 81 | ComputeAdr(x,y);
|
---|
| 82 | r = *_adr; _adr++;
|
---|
| 83 | g = *_adr; _adr++;
|
---|
| 84 | b = *_adr;
|
---|
| 85 | }
|
---|
| 86 | // save to a file of a given name - return 0 on success
|
---|
| 87 | int SaveToFile(const char *filename);
|
---|
| 88 | };
|
---|
| 89 |
|
---|
| 90 | inline int
|
---|
| 91 | CTGAImage::SaveToFile(const char *filename)
|
---|
| 92 | {
|
---|
| 93 | int i, j;
|
---|
| 94 |
|
---|
| 95 | int channelNum = CHANNELS;
|
---|
| 96 | int width = _width;
|
---|
| 97 | int height = _height;
|
---|
| 98 |
|
---|
| 99 | // Only 3 or 4 channels in file are supported
|
---|
| 100 | if (channelNum != 3 && channelNum != 4) {
|
---|
| 101 | cerr << "Invalid number of channels: " << channelNum << '\n';
|
---|
| 102 | cerr << "Only 3 or 4 channels in file are supported\n";
|
---|
| 103 | return 1; // error
|
---|
| 104 | }
|
---|
| 105 | FILE *f = fopen(filename,"wb");
|
---|
| 106 | if (!f)
|
---|
| 107 | return 1; // file cannot be opened
|
---|
| 108 |
|
---|
| 109 | printf("Saving image (%d x %d) to a file %s \n", width, height, filename);
|
---|
| 110 |
|
---|
| 111 | fprintf(f,"%c", 0); // CImage ID length (no image ID = 0)
|
---|
| 112 | fprintf(f,"%c", 0); // Colormap type (no colormap = 0)
|
---|
| 113 | fprintf(f,"%c", 2); // CImage type (uncompressed true-color = 2)
|
---|
| 114 | // Color Map specification (0 - no colormap)
|
---|
| 115 | fprintf(f,"%c%c%c%c%c",0,0,0,0,0);
|
---|
| 116 | fprintf(f,"%c%c", 0, 0); // X image origin (0 - no offset)
|
---|
| 117 | fprintf(f,"%c%c", 0, 0); // Y image origin (0 - no offset)
|
---|
| 118 | // CImage width
|
---|
| 119 | fprintf(f,"%c%c", ((unsigned char)(width >> 0)), ((unsigned char)(width >> 8)));
|
---|
| 120 | // CImage height
|
---|
| 121 | fprintf(f,"%c%c", ((unsigned char)(height >> 0)), ((unsigned char)(height >> 8)));
|
---|
| 122 | // Pixel depth (24 or 32 bpp: true-color)
|
---|
| 123 | fprintf(f,"%c", (channelNum * 8));
|
---|
| 124 |
|
---|
| 125 | if (channelNum == 4) // CImage descriptor
|
---|
| 126 | fprintf(f,"%c", 0x28); // 0010X000 - 00 - unused
|
---|
| 127 | else // 10 - left-to-right,top-to-bottom
|
---|
| 128 | fprintf(f,"%c", 0x20); // 0000 or 1000 - no alpha or
|
---|
| 129 | // 1 byte of alpha
|
---|
| 130 | // CImage ID not used
|
---|
| 131 | // CImage colormap not used
|
---|
| 132 | // CImage data follows (RGB triplets)
|
---|
| 133 | fflush(f);
|
---|
| 134 |
|
---|
| 135 | for (j = 0; j < height; j++){
|
---|
| 136 | for (i = 0; i < width; i++) {
|
---|
| 137 | ComputeAdr(i, j);
|
---|
| 138 | unsigned char val;
|
---|
| 139 |
|
---|
| 140 | float r,g,b;
|
---|
| 141 | r = *_adr; _adr++;
|
---|
| 142 | g = *_adr; _adr++;
|
---|
| 143 | b = *_adr;
|
---|
| 144 |
|
---|
| 145 | if (channelNum >= 3) {
|
---|
| 146 | if (b > 255.f) b = 255.f;
|
---|
| 147 | val = (unsigned char) b; // Blue
|
---|
| 148 | fprintf(f,"%c", val); // Blue
|
---|
| 149 | }
|
---|
| 150 | if (channelNum >= 2) {
|
---|
| 151 | if (g > 255.f) g = 255.f;
|
---|
| 152 | val = (unsigned char) g; // Green
|
---|
| 153 | fprintf(f,"%c", val); // Green
|
---|
| 154 | }
|
---|
| 155 | if (channelNum >= 1) {
|
---|
| 156 | if (r > 255.f) r = 255.f;
|
---|
| 157 | val = (unsigned char) r; // Red
|
---|
| 158 | fprintf(f,"%c", val); // Red
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 | if (channelNum == 4) {
|
---|
| 162 | _adr++; // alpha value should be in range 0.0-1.0
|
---|
| 163 | float a = *_adr;
|
---|
| 164 | fprintf(f,"%c", (unsigned char)(255.0 * a)); // Alpha
|
---|
| 165 | }
|
---|
| 166 | }
|
---|
| 167 | }
|
---|
| 168 | fflush(f);
|
---|
| 169 | fprintf(f,"%c%c%c%c",0,0,0,0); // no extension area - offset = 0
|
---|
| 170 | fprintf(f,"%c%c%c%c",0,0,0,0); // no developers directory - offset = 0
|
---|
| 171 | fprintf(f,"TRUEVISION-XFILE."); // new TGA signature
|
---|
| 172 | fclose(f);
|
---|
| 173 | return 0; // ok
|
---|
| 174 | }
|
---|
| 175 |
|
---|
| 176 | #endif // __TGAIMG_H__
|
---|
| 177 |
|
---|