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.
25 ** RGB Image Structure
28 typedef struct _TK_RGBImageRec
{
36 /******************************************************************************/
38 typedef struct _rawImageRec
{
39 unsigned short imagic
;
42 unsigned short sizeX
, sizeY
, sizeZ
;
43 unsigned long min
, max
;
44 unsigned long wasteBytes
;
46 unsigned long colorMap
;
48 unsigned char *tmp
, *tmpR
, *tmpG
, *tmpB
, *tmpA
;
54 /******************************************************************************/
56 static void ConvertShort(unsigned short *array
, long length
)
61 ptr
= (unsigned char *)array
;
65 *array
++ = (unsigned short) ((b1
<< 8) | (b2
));
69 static void ConvertLong(GLuint
*array
, long length
)
71 unsigned long b1
, b2
, b3
, b4
;
74 ptr
= (unsigned char *)array
;
80 *array
++ = (b1
<< 24) | (b2
<< 16) | (b3
<< 8) | (b4
);
84 static rawImageRec
*RawImageOpen(const char *fileName
)
95 endianTest
.testWord
= 1;
96 if (endianTest
.testByte
[0] == 1) {
102 raw
= (rawImageRec
*)calloc(1, sizeof(rawImageRec
));
104 fprintf(stderr
, "Out of memory!\n");
107 raw
->file
= fopen(fileName
, "rb");
108 if (raw
->file
== NULL
) {
109 const char *baseName
= strrchr(fileName
, '/');
111 raw
->file
= fopen(baseName
+ 1, "rb");
112 if(raw
->file
== NULL
) {
119 result
= fread(raw
, 1, 12, raw
->file
);
120 assert(result
== 12);
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);
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);
136 raw
->tmpA
= (unsigned char *)malloc(raw
->sizeX
*256);
138 if (raw
->tmp
== NULL
|| raw
->tmpR
== NULL
|| raw
->tmpG
== NULL
||
140 fprintf(stderr
, "Out of memory!\n");
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");
166 raw
->rleEnd
= 512 + (2 * x
);
167 fseek(raw
->file
, 512, SEEK_SET
);
168 result
= fread(raw
->rowStart
, 1, x
, raw
->file
);
170 result
= fread(raw
->rowSize
, 1, x
, raw
->file
);
173 ConvertLong(raw
->rowStart
, (long) (x
/sizeof(GLuint
)));
174 ConvertLong((GLuint
*)raw
->rowSize
, (long) (x
/sizeof(GLint
)));
180 static void RawImageClose(rawImageRec
*raw
)
197 static void RawImageGetRow(rawImageRec
*raw
, unsigned char *buf
, int y
, int z
)
199 unsigned char *iPtr
, *oPtr
, pixel
;
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
],
207 assert(result
== (unsigned int)raw
->rowSize
[y
+z
*raw
->sizeY
]);
213 count
= (int)(pixel
& 0x7F);
230 fseek(raw
->file
, 512+(y
*raw
->sizeX
)+(z
*raw
->sizeX
*raw
->sizeY
),
232 result
= fread(buf
, 1, raw
->sizeX
, raw
->file
);
233 assert(result
== raw
->sizeX
);
238 static void RawImageGetData(rawImageRec
*raw
, TK_RGBImageRec
*final
)
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");
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);
255 RawImageGetRow(raw
, raw
->tmpA
, i
, 3);
257 for (j
= 0; j
< (int)(raw
->sizeX
); j
++) {
258 *ptr
++ = *(raw
->tmpR
+ j
);
259 *ptr
++ = *(raw
->tmpG
+ j
);
260 *ptr
++ = *(raw
->tmpB
+ j
);
262 *ptr
++ = *(raw
->tmpA
+ j
);
269 static TK_RGBImageRec
*tkRGBImageLoad(const char *fileName
)
272 TK_RGBImageRec
*final
;
274 raw
= RawImageOpen(fileName
);
276 fprintf(stderr
, "File not found\n");
279 final
= (TK_RGBImageRec
*)malloc(sizeof(TK_RGBImageRec
));
281 fprintf(stderr
, "Out of memory!\n");
285 final
->sizeX
= raw
->sizeX
;
286 final
->sizeY
= raw
->sizeY
;
287 final
->components
= raw
->sizeZ
;
288 RawImageGetData(raw
, final
);
294 static void FreeImage( TK_RGBImageRec
*image
)
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.
307 GLboolean
LoadRGBMipmaps( const char *imageFile
, GLint intFormat
)
310 return LoadRGBMipmaps2( imageFile
, GL_TEXTURE_2D
, intFormat
, &w
, &h
);
315 GLboolean
LoadRGBMipmaps2( const char *imageFile
, GLenum target
,
316 GLint intFormat
, GLint
*width
, GLint
*height
)
320 TK_RGBImageRec
*image
;
322 image
= tkRGBImageLoad( imageFile
);
327 if (image
->components
==3) {
330 else if (image
->components
==4) {
334 /* not implemented */
336 "Error in LoadRGBMipmaps %d-component images not implemented\n",
342 error
= gluBuild2DMipmaps( target
,
344 image
->sizeX
, image
->sizeY
,
349 *width
= image
->sizeX
;
350 *height
= image
->sizeY
;
354 return error
? GL_FALSE
: GL_TRUE
;
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
367 GLubyte
*LoadRGBImage( const char *imageFile
, GLint
*width
, GLint
*height
,
370 TK_RGBImageRec
*image
;
374 image
= tkRGBImageLoad( imageFile
);
379 if (image
->components
==3) {
382 else if (image
->components
==4) {
386 /* not implemented */
388 "Error in LoadRGBImage %d-component images not implemented\n",
394 *width
= image
->sizeX
;
395 *height
= image
->sizeY
;
397 bytes
= image
->sizeX
* image
->sizeY
* image
->components
;
398 buffer
= (GLubyte
*) malloc(bytes
);
404 memcpy( (void *) buffer
, (void *) image
->data
, bytes
);
411 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
414 static void ConvertRGBtoYUV(GLint w
, GLint h
, GLint texel_bytes
,
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;
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);
438 *dest
= (iy
<< 8) | icr
;
442 *dest
= (iy
<< 8) | icb
;
452 * Load an SGI .rgb file and return a pointer to the image data, converted
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
460 GLushort
*LoadYUVImage( const char *imageFile
, GLint
*width
, GLint
*height
)
462 TK_RGBImageRec
*image
;
465 image
= tkRGBImageLoad( imageFile
);
470 if (image
->components
!= 3 && image
->components
!=4 ) {
471 /* not implemented */
473 "Error in LoadYUVImage %d-component images not implemented\n",
479 *width
= image
->sizeX
;
480 *height
= image
->sizeY
;
482 buffer
= (GLushort
*) malloc( image
->sizeX
* image
->sizeY
* 2 );
485 ConvertRGBtoYUV( image
->sizeX
,