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.
24 ** RGB Image Structure
27 typedef struct _TK_RGBImageRec
{
35 /******************************************************************************/
37 typedef struct _rawImageRec
{
38 unsigned short imagic
;
41 unsigned short sizeX
, sizeY
, sizeZ
;
42 unsigned long min
, max
;
43 unsigned long wasteBytes
;
45 unsigned long colorMap
;
47 unsigned char *tmp
, *tmpR
, *tmpG
, *tmpB
, *tmpA
;
53 /******************************************************************************/
55 static void ConvertShort(unsigned short *array
, long length
)
60 ptr
= (unsigned char *)array
;
64 *array
++ = (unsigned short) ((b1
<< 8) | (b2
));
68 static void ConvertLong(GLuint
*array
, long length
)
70 unsigned long b1
, b2
, b3
, b4
;
73 ptr
= (unsigned char *)array
;
79 *array
++ = (b1
<< 24) | (b2
<< 16) | (b3
<< 8) | (b4
);
83 static rawImageRec
*RawImageOpen(const char *fileName
)
93 endianTest
.testWord
= 1;
94 if (endianTest
.testByte
[0] == 1) {
100 raw
= (rawImageRec
*)calloc(1, sizeof(rawImageRec
));
102 fprintf(stderr
, "Out of memory!\n");
105 raw
->file
= fopen(fileName
, "rb");
106 if (raw
->file
== NULL
) {
107 const char *baseName
= strrchr(fileName
, '/');
109 raw
->file
= fopen(baseName
+ 1, "rb");
110 if(raw
->file
== NULL
) {
117 fread(raw
, 1, 12, raw
->file
);
120 ConvertShort(&raw
->imagic
, 1);
121 ConvertShort(&raw
->type
, 1);
122 ConvertShort(&raw
->dim
, 1);
123 ConvertShort(&raw
->sizeX
, 1);
124 ConvertShort(&raw
->sizeY
, 1);
125 ConvertShort(&raw
->sizeZ
, 1);
128 raw
->tmp
= (unsigned char *)malloc(raw
->sizeX
*256);
129 raw
->tmpR
= (unsigned char *)malloc(raw
->sizeX
*256);
130 raw
->tmpG
= (unsigned char *)malloc(raw
->sizeX
*256);
131 raw
->tmpB
= (unsigned char *)malloc(raw
->sizeX
*256);
133 raw
->tmpA
= (unsigned char *)malloc(raw
->sizeX
*256);
135 if (raw
->tmp
== NULL
|| raw
->tmpR
== NULL
|| raw
->tmpG
== NULL
||
137 fprintf(stderr
, "Out of memory!\n");
147 if ((raw
->type
& 0xFF00) == 0x0100) {
148 x
= raw
->sizeY
* raw
->sizeZ
* sizeof(GLuint
);
149 raw
->rowStart
= (GLuint
*)malloc(x
);
150 raw
->rowSize
= (GLint
*)malloc(x
);
151 if (raw
->rowStart
== NULL
|| raw
->rowSize
== NULL
) {
152 fprintf(stderr
, "Out of memory!\n");
163 raw
->rleEnd
= 512 + (2 * x
);
164 fseek(raw
->file
, 512, SEEK_SET
);
165 fread(raw
->rowStart
, 1, x
, raw
->file
);
166 fread(raw
->rowSize
, 1, x
, raw
->file
);
168 ConvertLong(raw
->rowStart
, (long) (x
/sizeof(GLuint
)));
169 ConvertLong((GLuint
*)raw
->rowSize
, (long) (x
/sizeof(GLint
)));
175 static void RawImageClose(rawImageRec
*raw
)
192 static void RawImageGetRow(rawImageRec
*raw
, unsigned char *buf
, int y
, int z
)
194 unsigned char *iPtr
, *oPtr
, pixel
;
197 if ((raw
->type
& 0xFF00) == 0x0100) {
198 fseek(raw
->file
, (long) raw
->rowStart
[y
+z
*raw
->sizeY
], SEEK_SET
);
199 fread(raw
->tmp
, 1, (unsigned int)raw
->rowSize
[y
+z
*raw
->sizeY
],
206 count
= (int)(pixel
& 0x7F);
223 fseek(raw
->file
, 512+(y
*raw
->sizeX
)+(z
*raw
->sizeX
*raw
->sizeY
),
225 fread(buf
, 1, raw
->sizeX
, raw
->file
);
230 static void RawImageGetData(rawImageRec
*raw
, TK_RGBImageRec
*final
)
235 final
->data
= (unsigned char *)malloc((raw
->sizeX
+1)*(raw
->sizeY
+1)*4);
236 if (final
->data
== NULL
) {
237 fprintf(stderr
, "Out of memory!\n");
242 for (i
= 0; i
< (int)(raw
->sizeY
); i
++) {
243 RawImageGetRow(raw
, raw
->tmpR
, i
, 0);
244 RawImageGetRow(raw
, raw
->tmpG
, i
, 1);
245 RawImageGetRow(raw
, raw
->tmpB
, i
, 2);
247 RawImageGetRow(raw
, raw
->tmpA
, i
, 3);
249 for (j
= 0; j
< (int)(raw
->sizeX
); j
++) {
250 *ptr
++ = *(raw
->tmpR
+ j
);
251 *ptr
++ = *(raw
->tmpG
+ j
);
252 *ptr
++ = *(raw
->tmpB
+ j
);
254 *ptr
++ = *(raw
->tmpA
+ j
);
261 static TK_RGBImageRec
*tkRGBImageLoad(const char *fileName
)
264 TK_RGBImageRec
*final
;
266 raw
= RawImageOpen(fileName
);
268 fprintf(stderr
, "File not found\n");
271 final
= (TK_RGBImageRec
*)malloc(sizeof(TK_RGBImageRec
));
273 fprintf(stderr
, "Out of memory!\n");
277 final
->sizeX
= raw
->sizeX
;
278 final
->sizeY
= raw
->sizeY
;
279 final
->components
= raw
->sizeZ
;
280 RawImageGetData(raw
, final
);
286 static void FreeImage( TK_RGBImageRec
*image
)
294 * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
295 * Input: imageFile - name of .rgb to read
296 * intFormat - internal texture format to use, or number of components
297 * Return: GL_TRUE if success, GL_FALSE if error.
299 GLboolean
LoadRGBMipmaps( const char *imageFile
, GLint intFormat
)
302 return LoadRGBMipmaps2( imageFile
, GL_TEXTURE_2D
, intFormat
, &w
, &h
);
307 GLboolean
LoadRGBMipmaps2( const char *imageFile
, GLenum target
,
308 GLint intFormat
, GLint
*width
, GLint
*height
)
312 TK_RGBImageRec
*image
;
314 image
= tkRGBImageLoad( imageFile
);
319 if (image
->components
==3) {
322 else if (image
->components
==4) {
326 /* not implemented */
328 "Error in LoadRGBMipmaps %d-component images not implemented\n",
334 error
= gluBuild2DMipmaps( target
,
336 image
->sizeX
, image
->sizeY
,
341 *width
= image
->sizeX
;
342 *height
= image
->sizeY
;
346 return error
? GL_FALSE
: GL_TRUE
;
352 * Load an SGI .rgb file and return a pointer to the image data.
353 * Input: imageFile - name of .rgb to read
354 * Output: width - width of image
355 * height - height of image
356 * format - format of image (GL_RGB or GL_RGBA)
357 * Return: pointer to image data or NULL if error
359 GLubyte
*LoadRGBImage( const char *imageFile
, GLint
*width
, GLint
*height
,
362 TK_RGBImageRec
*image
;
366 image
= tkRGBImageLoad( imageFile
);
371 if (image
->components
==3) {
374 else if (image
->components
==4) {
378 /* not implemented */
380 "Error in LoadRGBImage %d-component images not implemented\n",
386 *width
= image
->sizeX
;
387 *height
= image
->sizeY
;
389 bytes
= image
->sizeX
* image
->sizeY
* image
->components
;
390 buffer
= (GLubyte
*) malloc(bytes
);
396 memcpy( (void *) buffer
, (void *) image
->data
, bytes
);
403 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
406 static void ConvertRGBtoYUV(GLint w
, GLint h
, GLint texel_bytes
,
412 for (i
= 0; i
< h
; i
++) {
413 for (j
= 0; j
< w
; j
++) {
414 const GLfloat r
= (src
[0]) / 255.0;
415 const GLfloat g
= (src
[1]) / 255.0;
416 const GLfloat b
= (src
[2]) / 255.0;
420 y
= r
* 65.481 + g
* 128.553 + b
* 24.966 + 16;
421 cb
= r
* -37.797 + g
* -74.203 + b
* 112.0 + 128;
422 cr
= r
* 112.0 + g
* -93.786 + b
* -18.214 + 128;
423 /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/
424 iy
= (GLint
) CLAMP(y
, 0, 254);
425 icb
= (GLint
) CLAMP(cb
, 0, 254);
426 icr
= (GLint
) CLAMP(cr
, 0, 254);
430 *dest
= (iy
<< 8) | icr
;
434 *dest
= (iy
<< 8) | icb
;
444 * Load an SGI .rgb file and return a pointer to the image data, converted
447 * Input: imageFile - name of .rgb to read
448 * Output: width - width of image
449 * height - height of image
450 * Return: pointer to image data or NULL if error
452 GLushort
*LoadYUVImage( const char *imageFile
, GLint
*width
, GLint
*height
)
454 TK_RGBImageRec
*image
;
457 image
= tkRGBImageLoad( imageFile
);
462 if (image
->components
!= 3 && image
->components
!=4 ) {
463 /* not implemented */
465 "Error in LoadYUVImage %d-component images not implemented\n",
471 *width
= image
->sizeX
;
472 *height
= image
->sizeY
;
474 buffer
= (GLushort
*) malloc( image
->sizeX
* image
->sizeY
* 2 );
477 ConvertRGBtoYUV( image
->sizeX
,