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 |
|
---|