progs/vp: more psiz tests
[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 #include "readtex.h"
16
17
18 #ifndef SEEK_SET
19 # define SEEK_SET 0
20 #endif
21
22
23 /*
24 ** RGB Image Structure
25 */
26
27 typedef struct _TK_RGBImageRec {
28 GLint sizeX, sizeY;
29 GLint components;
30 unsigned char *data;
31 } TK_RGBImageRec;
32
33
34
35 /******************************************************************************/
36
37 typedef struct _rawImageRec {
38 unsigned short imagic;
39 unsigned short type;
40 unsigned short dim;
41 unsigned short sizeX, sizeY, sizeZ;
42 unsigned long min, max;
43 unsigned long wasteBytes;
44 char name[80];
45 unsigned long colorMap;
46 FILE *file;
47 unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
48 unsigned long rleEnd;
49 GLuint *rowStart;
50 GLint *rowSize;
51 } rawImageRec;
52
53 /******************************************************************************/
54
55 static void ConvertShort(unsigned short *array, long length)
56 {
57 unsigned long b1, b2;
58 unsigned char *ptr;
59
60 ptr = (unsigned char *)array;
61 while (length--) {
62 b1 = *ptr++;
63 b2 = *ptr++;
64 *array++ = (unsigned short) ((b1 << 8) | (b2));
65 }
66 }
67
68 static void ConvertLong(GLuint *array, long length)
69 {
70 unsigned long b1, b2, b3, b4;
71 unsigned char *ptr;
72
73 ptr = (unsigned char *)array;
74 while (length--) {
75 b1 = *ptr++;
76 b2 = *ptr++;
77 b3 = *ptr++;
78 b4 = *ptr++;
79 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
80 }
81 }
82
83 static rawImageRec *RawImageOpen(const char *fileName)
84 {
85 union {
86 int testWord;
87 char testByte[4];
88 } endianTest;
89 rawImageRec *raw;
90 GLenum swapFlag;
91 int x;
92
93 endianTest.testWord = 1;
94 if (endianTest.testByte[0] == 1) {
95 swapFlag = GL_TRUE;
96 } else {
97 swapFlag = GL_FALSE;
98 }
99
100 raw = (rawImageRec *)calloc(1, sizeof(rawImageRec));
101 if (raw == NULL) {
102 fprintf(stderr, "Out of memory!\n");
103 return NULL;
104 }
105 raw->file = fopen(fileName, "rb");
106 if (raw->file == NULL) {
107 const char *baseName = strrchr(fileName, '/');
108 if(baseName)
109 raw->file = fopen(baseName + 1, "rb");
110 if(raw->file == NULL) {
111 perror(fileName);
112 return NULL;
113 }
114 }
115
116 fread(raw, 1, 12, raw->file);
117
118 if (swapFlag) {
119 ConvertShort(&raw->imagic, 6);
120 }
121
122 raw->tmp = (unsigned char *)malloc(raw->sizeX*256);
123 raw->tmpR = (unsigned char *)malloc(raw->sizeX*256);
124 raw->tmpG = (unsigned char *)malloc(raw->sizeX*256);
125 raw->tmpB = (unsigned char *)malloc(raw->sizeX*256);
126 if (raw->sizeZ==4) {
127 raw->tmpA = (unsigned char *)malloc(raw->sizeX*256);
128 }
129 if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||
130 raw->tmpB == NULL) {
131 fprintf(stderr, "Out of memory!\n");
132 return NULL;
133 }
134
135 if ((raw->type & 0xFF00) == 0x0100) {
136 x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
137 raw->rowStart = (GLuint *)malloc(x);
138 raw->rowSize = (GLint *)malloc(x);
139 if (raw->rowStart == NULL || raw->rowSize == NULL) {
140 fprintf(stderr, "Out of memory!\n");
141 return NULL;
142 }
143 raw->rleEnd = 512 + (2 * x);
144 fseek(raw->file, 512, SEEK_SET);
145 fread(raw->rowStart, 1, x, raw->file);
146 fread(raw->rowSize, 1, x, raw->file);
147 if (swapFlag) {
148 ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
149 ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
150 }
151 }
152 return raw;
153 }
154
155 static void RawImageClose(rawImageRec *raw)
156 {
157 fclose(raw->file);
158 free(raw->tmp);
159 free(raw->tmpR);
160 free(raw->tmpG);
161 free(raw->tmpB);
162 if (raw->rowStart)
163 free(raw->rowStart);
164 if (raw->rowSize)
165 free(raw->rowSize);
166 if (raw->sizeZ>3) {
167 free(raw->tmpA);
168 }
169 free(raw);
170 }
171
172 static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
173 {
174 unsigned char *iPtr, *oPtr, pixel;
175 int count, done = 0;
176
177 if ((raw->type & 0xFF00) == 0x0100) {
178 fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET);
179 fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY],
180 raw->file);
181
182 iPtr = raw->tmp;
183 oPtr = buf;
184 while (!done) {
185 pixel = *iPtr++;
186 count = (int)(pixel & 0x7F);
187 if (!count) {
188 done = 1;
189 return;
190 }
191 if (pixel & 0x80) {
192 while (count--) {
193 *oPtr++ = *iPtr++;
194 }
195 } else {
196 pixel = *iPtr++;
197 while (count--) {
198 *oPtr++ = pixel;
199 }
200 }
201 }
202 } else {
203 fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY),
204 SEEK_SET);
205 fread(buf, 1, raw->sizeX, raw->file);
206 }
207 }
208
209
210 static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final)
211 {
212 unsigned char *ptr;
213 int i, j;
214
215 final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4);
216 if (final->data == NULL) {
217 fprintf(stderr, "Out of memory!\n");
218 }
219
220 ptr = final->data;
221 for (i = 0; i < (int)(raw->sizeY); i++) {
222 RawImageGetRow(raw, raw->tmpR, i, 0);
223 RawImageGetRow(raw, raw->tmpG, i, 1);
224 RawImageGetRow(raw, raw->tmpB, i, 2);
225 if (raw->sizeZ>3) {
226 RawImageGetRow(raw, raw->tmpA, i, 3);
227 }
228 for (j = 0; j < (int)(raw->sizeX); j++) {
229 *ptr++ = *(raw->tmpR + j);
230 *ptr++ = *(raw->tmpG + j);
231 *ptr++ = *(raw->tmpB + j);
232 if (raw->sizeZ>3) {
233 *ptr++ = *(raw->tmpA + j);
234 }
235 }
236 }
237 }
238
239
240 static TK_RGBImageRec *tkRGBImageLoad(const char *fileName)
241 {
242 rawImageRec *raw;
243 TK_RGBImageRec *final;
244
245 raw = RawImageOpen(fileName);
246 if (!raw) {
247 fprintf(stderr, "File not found\n");
248 return NULL;
249 }
250 final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec));
251 if (final == NULL) {
252 fprintf(stderr, "Out of memory!\n");
253 return NULL;
254 }
255 final->sizeX = raw->sizeX;
256 final->sizeY = raw->sizeY;
257 final->components = raw->sizeZ;
258 RawImageGetData(raw, final);
259 RawImageClose(raw);
260 return final;
261 }
262
263
264 static void FreeImage( TK_RGBImageRec *image )
265 {
266 free(image->data);
267 free(image);
268 }
269
270
271 /*
272 * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
273 * Input: imageFile - name of .rgb to read
274 * intFormat - internal texture format to use, or number of components
275 * Return: GL_TRUE if success, GL_FALSE if error.
276 */
277 GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat )
278 {
279 GLint w, h;
280 return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h );
281 }
282
283
284
285 GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target,
286 GLint intFormat, GLint *width, GLint *height )
287 {
288 GLint error;
289 GLenum format;
290 TK_RGBImageRec *image;
291
292 image = tkRGBImageLoad( imageFile );
293 if (!image) {
294 return GL_FALSE;
295 }
296
297 if (image->components==3) {
298 format = GL_RGB;
299 }
300 else if (image->components==4) {
301 format = GL_RGBA;
302 }
303 else {
304 /* not implemented */
305 fprintf(stderr,
306 "Error in LoadRGBMipmaps %d-component images not implemented\n",
307 image->components );
308 return GL_FALSE;
309 }
310
311 error = gluBuild2DMipmaps( target,
312 intFormat,
313 image->sizeX, image->sizeY,
314 format,
315 GL_UNSIGNED_BYTE,
316 image->data );
317
318 *width = image->sizeX;
319 *height = image->sizeY;
320
321 FreeImage(image);
322
323 return error ? GL_FALSE : GL_TRUE;
324 }
325
326
327
328 /*
329 * Load an SGI .rgb file and return a pointer to the image data.
330 * Input: imageFile - name of .rgb to read
331 * Output: width - width of image
332 * height - height of image
333 * format - format of image (GL_RGB or GL_RGBA)
334 * Return: pointer to image data or NULL if error
335 */
336 GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height,
337 GLenum *format )
338 {
339 TK_RGBImageRec *image;
340 GLint bytes;
341 GLubyte *buffer;
342
343 image = tkRGBImageLoad( imageFile );
344 if (!image) {
345 return NULL;
346 }
347
348 if (image->components==3) {
349 *format = GL_RGB;
350 }
351 else if (image->components==4) {
352 *format = GL_RGBA;
353 }
354 else {
355 /* not implemented */
356 fprintf(stderr,
357 "Error in LoadRGBImage %d-component images not implemented\n",
358 image->components );
359 return NULL;
360 }
361
362 *width = image->sizeX;
363 *height = image->sizeY;
364
365 bytes = image->sizeX * image->sizeY * image->components;
366 buffer = (GLubyte *) malloc(bytes);
367 if (!buffer)
368 return NULL;
369
370 memcpy( (void *) buffer, (void *) image->data, bytes );
371
372 FreeImage(image);
373
374 return buffer;
375 }
376
377 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
378
379
380 static void ConvertRGBtoYUV(GLint w, GLint h, GLint texel_bytes,
381 const GLubyte *src,
382 GLushort *dest)
383 {
384 GLint i, j;
385
386 for (i = 0; i < h; i++) {
387 for (j = 0; j < w; j++) {
388 const GLfloat r = (src[0]) / 255.0;
389 const GLfloat g = (src[1]) / 255.0;
390 const GLfloat b = (src[2]) / 255.0;
391 GLfloat y, cr, cb;
392 GLint iy, icr, icb;
393
394 y = r * 65.481 + g * 128.553 + b * 24.966 + 16;
395 cb = r * -37.797 + g * -74.203 + b * 112.0 + 128;
396 cr = r * 112.0 + g * -93.786 + b * -18.214 + 128;
397 /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/
398 iy = (GLint) CLAMP(y, 0, 254);
399 icb = (GLint) CLAMP(cb, 0, 254);
400 icr = (GLint) CLAMP(cr, 0, 254);
401
402 if (j & 1) {
403 /* odd */
404 *dest = (iy << 8) | icr;
405 }
406 else {
407 /* even */
408 *dest = (iy << 8) | icb;
409 }
410 dest++;
411 src += texel_bytes;
412 }
413 }
414 }
415
416
417 /*
418 * Load an SGI .rgb file and return a pointer to the image data, converted
419 * to 422 yuv.
420 *
421 * Input: imageFile - name of .rgb to read
422 * Output: width - width of image
423 * height - height of image
424 * Return: pointer to image data or NULL if error
425 */
426 GLushort *LoadYUVImage( const char *imageFile, GLint *width, GLint *height )
427 {
428 TK_RGBImageRec *image;
429 GLushort *buffer;
430
431 image = tkRGBImageLoad( imageFile );
432 if (!image) {
433 return NULL;
434 }
435
436 if (image->components != 3 && image->components !=4 ) {
437 /* not implemented */
438 fprintf(stderr,
439 "Error in LoadYUVImage %d-component images not implemented\n",
440 image->components );
441 return NULL;
442 }
443
444 *width = image->sizeX;
445 *height = image->sizeY;
446
447 buffer = (GLushort *) malloc( image->sizeX * image->sizeY * 2 );
448
449 if (buffer)
450 ConvertRGBtoYUV( image->sizeX,
451 image->sizeY,
452 image->components,
453 image->data,
454 buffer );
455
456
457 FreeImage(image);
458 return buffer;
459 }
460