prevent spaces in fp register names
[mesa.git] / progs / util / readtex.c
1 /* readtex.c */
2
3 /*
4 * Read an SGI .rgb image file and generate a mipmap texture set.
5 * Much of this code was borrowed from SGI's tk OpenGL toolkit.
6 */
7
8
9
10 #include <GL/gl.h>
11 #include <GL/glu.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16
17 #ifndef SEEK_SET
18 # define SEEK_SET 0
19 #endif
20
21
22 /*
23 ** RGB Image Structure
24 */
25
26 typedef struct _TK_RGBImageRec {
27 GLint sizeX, sizeY;
28 GLint components;
29 unsigned char *data;
30 } TK_RGBImageRec;
31
32
33
34 /******************************************************************************/
35
36 typedef struct _rawImageRec {
37 unsigned short imagic;
38 unsigned short type;
39 unsigned short dim;
40 unsigned short sizeX, sizeY, sizeZ;
41 unsigned long min, max;
42 unsigned long wasteBytes;
43 char name[80];
44 unsigned long colorMap;
45 FILE *file;
46 unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
47 unsigned long rleEnd;
48 GLuint *rowStart;
49 GLint *rowSize;
50 } rawImageRec;
51
52 /******************************************************************************/
53
54 static void ConvertShort(unsigned short *array, long length)
55 {
56 unsigned long b1, b2;
57 unsigned char *ptr;
58
59 ptr = (unsigned char *)array;
60 while (length--) {
61 b1 = *ptr++;
62 b2 = *ptr++;
63 *array++ = (unsigned short) ((b1 << 8) | (b2));
64 }
65 }
66
67 static void ConvertLong(GLuint *array, long length)
68 {
69 unsigned long b1, b2, b3, b4;
70 unsigned char *ptr;
71
72 ptr = (unsigned char *)array;
73 while (length--) {
74 b1 = *ptr++;
75 b2 = *ptr++;
76 b3 = *ptr++;
77 b4 = *ptr++;
78 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
79 }
80 }
81
82 static rawImageRec *RawImageOpen(const char *fileName)
83 {
84 union {
85 int testWord;
86 char testByte[4];
87 } endianTest;
88 rawImageRec *raw;
89 GLenum swapFlag;
90 int x;
91
92 endianTest.testWord = 1;
93 if (endianTest.testByte[0] == 1) {
94 swapFlag = GL_TRUE;
95 } else {
96 swapFlag = GL_FALSE;
97 }
98
99 raw = (rawImageRec *)malloc(sizeof(rawImageRec));
100 if (raw == NULL) {
101 fprintf(stderr, "Out of memory!\n");
102 return NULL;
103 }
104 if ((raw->file = fopen(fileName, "rb")) == NULL) {
105 perror(fileName);
106 return NULL;
107 }
108
109 fread(raw, 1, 12, raw->file);
110
111 if (swapFlag) {
112 ConvertShort(&raw->imagic, 6);
113 }
114
115 raw->tmp = (unsigned char *)malloc(raw->sizeX*256);
116 raw->tmpR = (unsigned char *)malloc(raw->sizeX*256);
117 raw->tmpG = (unsigned char *)malloc(raw->sizeX*256);
118 raw->tmpB = (unsigned char *)malloc(raw->sizeX*256);
119 if (raw->sizeZ==4) {
120 raw->tmpA = (unsigned char *)malloc(raw->sizeX*256);
121 }
122 if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||
123 raw->tmpB == NULL) {
124 fprintf(stderr, "Out of memory!\n");
125 return NULL;
126 }
127
128 if ((raw->type & 0xFF00) == 0x0100) {
129 x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
130 raw->rowStart = (GLuint *)malloc(x);
131 raw->rowSize = (GLint *)malloc(x);
132 if (raw->rowStart == NULL || raw->rowSize == NULL) {
133 fprintf(stderr, "Out of memory!\n");
134 return NULL;
135 }
136 raw->rleEnd = 512 + (2 * x);
137 fseek(raw->file, 512, SEEK_SET);
138 fread(raw->rowStart, 1, x, raw->file);
139 fread(raw->rowSize, 1, x, raw->file);
140 if (swapFlag) {
141 ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
142 ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
143 }
144 }
145 return raw;
146 }
147
148 static void RawImageClose(rawImageRec *raw)
149 {
150
151 fclose(raw->file);
152 free(raw->tmp);
153 free(raw->tmpR);
154 free(raw->tmpG);
155 free(raw->tmpB);
156 if (raw->sizeZ>3) {
157 free(raw->tmpA);
158 }
159 free(raw);
160 }
161
162 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
163 {
164 unsigned char *iPtr, *oPtr, pixel;
165 int count, done = 0;
166
167 if ((raw->type & 0xFF00) == 0x0100) {
168 fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET);
169 fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY],
170 raw->file);
171
172 iPtr = raw->tmp;
173 oPtr = buf;
174 while (!done) {
175 pixel = *iPtr++;
176 count = (int)(pixel & 0x7F);
177 if (!count) {
178 done = 1;
179 return;
180 }
181 if (pixel & 0x80) {
182 while (count--) {
183 *oPtr++ = *iPtr++;
184 }
185 } else {
186 pixel = *iPtr++;
187 while (count--) {
188 *oPtr++ = pixel;
189 }
190 }
191 }
192 } else {
193 fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY),
194 SEEK_SET);
195 fread(buf, 1, raw->sizeX, raw->file);
196 }
197 }
198
199
200 static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final)
201 {
202 unsigned char *ptr;
203 int i, j;
204
205 final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4);
206 if (final->data == NULL) {
207 fprintf(stderr, "Out of memory!\n");
208 }
209
210 ptr = final->data;
211 for (i = 0; i < (int)(raw->sizeY); i++) {
212 RawImageGetRow(raw, raw->tmpR, i, 0);
213 RawImageGetRow(raw, raw->tmpG, i, 1);
214 RawImageGetRow(raw, raw->tmpB, i, 2);
215 if (raw->sizeZ>3) {
216 RawImageGetRow(raw, raw->tmpA, i, 3);
217 }
218 for (j = 0; j < (int)(raw->sizeX); j++) {
219 *ptr++ = *(raw->tmpR + j);
220 *ptr++ = *(raw->tmpG + j);
221 *ptr++ = *(raw->tmpB + j);
222 if (raw->sizeZ>3) {
223 *ptr++ = *(raw->tmpA + j);
224 }
225 }
226 }
227 }
228
229
230 static TK_RGBImageRec *tkRGBImageLoad(const char *fileName)
231 {
232 rawImageRec *raw;
233 TK_RGBImageRec *final;
234
235 raw = RawImageOpen(fileName);
236 if (!raw) {
237 fprintf(stderr, "File not found\n");
238 return NULL;
239 }
240 final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec));
241 if (final == NULL) {
242 fprintf(stderr, "Out of memory!\n");
243 return NULL;
244 }
245 final->sizeX = raw->sizeX;
246 final->sizeY = raw->sizeY;
247 final->components = raw->sizeZ;
248 RawImageGetData(raw, final);
249 RawImageClose(raw);
250 return final;
251 }
252
253
254 static void FreeImage( TK_RGBImageRec *image )
255 {
256 free(image->data);
257 free(image);
258 }
259
260
261 /*
262 * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
263 * Input: imageFile - name of .rgb to read
264 * intFormat - internal texture format to use, or number of components
265 * Return: GL_TRUE if success, GL_FALSE if error.
266 */
267 GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat )
268 {
269 GLint error;
270 GLenum format;
271 TK_RGBImageRec *image;
272
273 image = tkRGBImageLoad( imageFile );
274 if (!image) {
275 return GL_FALSE;
276 }
277
278 if (image->components==3) {
279 format = GL_RGB;
280 }
281 else if (image->components==4) {
282 format = GL_RGBA;
283 }
284 else {
285 /* not implemented */
286 fprintf(stderr,
287 "Error in LoadRGBMipmaps %d-component images not implemented\n",
288 image->components );
289 return GL_FALSE;
290 }
291
292 error = gluBuild2DMipmaps( GL_TEXTURE_2D,
293 intFormat,
294 image->sizeX, image->sizeY,
295 format,
296 GL_UNSIGNED_BYTE,
297 image->data );
298
299 FreeImage(image);
300 return error ? GL_FALSE : GL_TRUE;
301 }
302
303
304
305 /*
306 * Load an SGI .rgb file and return a pointer to the image data.
307 * Input: imageFile - name of .rgb to read
308 * Output: width - width of image
309 * height - height of image
310 * format - format of image (GL_RGB or GL_RGBA)
311 * Return: pointer to image data or NULL if error
312 */
313 GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height,
314 GLenum *format )
315 {
316 TK_RGBImageRec *image;
317 GLint bytes;
318 GLubyte *buffer;
319
320 image = tkRGBImageLoad( imageFile );
321 if (!image) {
322 return NULL;
323 }
324
325 if (image->components==3) {
326 *format = GL_RGB;
327 }
328 else if (image->components==4) {
329 *format = GL_RGBA;
330 }
331 else {
332 /* not implemented */
333 fprintf(stderr,
334 "Error in LoadRGBImage %d-component images not implemented\n",
335 image->components );
336 return NULL;
337 }
338
339 *width = image->sizeX;
340 *height = image->sizeY;
341
342 bytes = image->sizeX * image->sizeY * image->components;
343 buffer = (GLubyte *) malloc(bytes);
344 if (!buffer)
345 return NULL;
346
347 memcpy( (void *) buffer, (void *) image->data, bytes );
348
349 FreeImage(image);
350
351 return buffer;
352 }
353