~ubuntu-branches/ubuntu/quantal/mesa/quantal

« back to all changes in this revision

Viewing changes to progs/demos/readtex.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-02-21 12:44:07 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20070221124407-rgcacs32mycrtadl
ImportĀ upstreamĀ versionĀ 6.5.2

Show diffs side-by-side

added added

removed removed

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