~ubuntu-branches/ubuntu/oneiric/mesa-demos/oneiric

« back to all changes in this revision

Viewing changes to src/util/readtex.c

  • Committer: Bazaar Package Importer
  • Author(s): Christopher James Halse Rogers
  • Date: 2010-09-27 16:18:27 UTC
  • Revision ID: james.westby@ubuntu.com-20100927161827-1yfgolc1oy9sjhi8
Tags: upstream-8.0.1
ImportĀ upstreamĀ versionĀ 8.0.1

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