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
) {
116 fread(raw
, 1, 12, raw
->file
);
119 ConvertShort(&raw
->imagic
, 6);
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);
127 raw
->tmpA
= (unsigned char *)malloc(raw
->sizeX
*256);
129 if (raw
->tmp
== NULL
|| raw
->tmpR
== NULL
|| raw
->tmpG
== NULL
||
131 fprintf(stderr
, "Out of memory!\n");
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");
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
);
148 ConvertLong(raw
->rowStart
, (long) (x
/sizeof(GLuint
)));
149 ConvertLong((GLuint
*)raw
->rowSize
, (long) (x
/sizeof(GLint
)));
155 static void RawImageClose(rawImageRec
*raw
)
172 static void RawImageGetRow(rawImageRec
*raw
, unsigned char *buf
, int y
, int z
)
174 unsigned char *iPtr
, *oPtr
, pixel
;
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
],
186 count
= (int)(pixel
& 0x7F);
203 fseek(raw
->file
, 512+(y
*raw
->sizeX
)+(z
*raw
->sizeX
*raw
->sizeY
),
205 fread(buf
, 1, raw
->sizeX
, raw
->file
);
210 static void RawImageGetData(rawImageRec
*raw
, TK_RGBImageRec
*final
)
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");
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);
226 RawImageGetRow(raw
, raw
->tmpA
, i
, 3);
228 for (j
= 0; j
< (int)(raw
->sizeX
); j
++) {
229 *ptr
++ = *(raw
->tmpR
+ j
);
230 *ptr
++ = *(raw
->tmpG
+ j
);
231 *ptr
++ = *(raw
->tmpB
+ j
);
233 *ptr
++ = *(raw
->tmpA
+ j
);
240 static TK_RGBImageRec
*tkRGBImageLoad(const char *fileName
)
243 TK_RGBImageRec
*final
;
245 raw
= RawImageOpen(fileName
);
247 fprintf(stderr
, "File not found\n");
250 final
= (TK_RGBImageRec
*)malloc(sizeof(TK_RGBImageRec
));
252 fprintf(stderr
, "Out of memory!\n");
255 final
->sizeX
= raw
->sizeX
;
256 final
->sizeY
= raw
->sizeY
;
257 final
->components
= raw
->sizeZ
;
258 RawImageGetData(raw
, final
);
264 static void FreeImage( TK_RGBImageRec
*image
)
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.
277 GLboolean
LoadRGBMipmaps( const char *imageFile
, GLint intFormat
)
280 return LoadRGBMipmaps2( imageFile
, GL_TEXTURE_2D
, intFormat
, &w
, &h
);
285 GLboolean
LoadRGBMipmaps2( const char *imageFile
, GLenum target
,
286 GLint intFormat
, GLint
*width
, GLint
*height
)
290 TK_RGBImageRec
*image
;
292 image
= tkRGBImageLoad( imageFile
);
297 if (image
->components
==3) {
300 else if (image
->components
==4) {
304 /* not implemented */
306 "Error in LoadRGBMipmaps %d-component images not implemented\n",
311 error
= gluBuild2DMipmaps( target
,
313 image
->sizeX
, image
->sizeY
,
318 *width
= image
->sizeX
;
319 *height
= image
->sizeY
;
323 return error
? GL_FALSE
: GL_TRUE
;
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
336 GLubyte
*LoadRGBImage( const char *imageFile
, GLint
*width
, GLint
*height
,
339 TK_RGBImageRec
*image
;
343 image
= tkRGBImageLoad( imageFile
);
348 if (image
->components
==3) {
351 else if (image
->components
==4) {
355 /* not implemented */
357 "Error in LoadRGBImage %d-component images not implemented\n",
362 *width
= image
->sizeX
;
363 *height
= image
->sizeY
;
365 bytes
= image
->sizeX
* image
->sizeY
* image
->components
;
366 buffer
= (GLubyte
*) malloc(bytes
);
370 memcpy( (void *) buffer
, (void *) image
->data
, bytes
);
377 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
380 static void ConvertRGBtoYUV(GLint w
, GLint h
, GLint texel_bytes
,
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;
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);
404 *dest
= (iy
<< 8) | icr
;
408 *dest
= (iy
<< 8) | icb
;
418 * Load an SGI .rgb file and return a pointer to the image data, converted
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
426 GLushort
*LoadYUVImage( const char *imageFile
, GLint
*width
, GLint
*height
)
428 TK_RGBImageRec
*image
;
431 image
= tkRGBImageLoad( imageFile
);
436 if (image
->components
!= 3 && image
->components
!=4 ) {
437 /* not implemented */
439 "Error in LoadYUVImage %d-component images not implemented\n",
444 *width
= image
->sizeX
;
445 *height
= image
->sizeY
;
447 buffer
= (GLushort
*) malloc( image
->sizeX
* image
->sizeY
* 2 );
450 ConvertRGBtoYUV( image
->sizeX
,