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
, 6);
123 raw
->tmp
= (unsigned char *)malloc(raw
->sizeX
*256);
124 raw
->tmpR
= (unsigned char *)malloc(raw
->sizeX
*256);
125 raw
->tmpG
= (unsigned char *)malloc(raw
->sizeX
*256);
126 raw
->tmpB
= (unsigned char *)malloc(raw
->sizeX
*256);
128 raw
->tmpA
= (unsigned char *)malloc(raw
->sizeX
*256);
130 if (raw
->tmp
== NULL
|| raw
->tmpR
== NULL
|| raw
->tmpG
== NULL
||
132 fprintf(stderr
, "Out of memory!\n");
136 if ((raw
->type
& 0xFF00) == 0x0100) {
137 x
= raw
->sizeY
* raw
->sizeZ
* sizeof(GLuint
);
138 raw
->rowStart
= (GLuint
*)malloc(x
);
139 raw
->rowSize
= (GLint
*)malloc(x
);
140 if (raw
->rowStart
== NULL
|| raw
->rowSize
== NULL
) {
141 fprintf(stderr
, "Out of memory!\n");
144 raw
->rleEnd
= 512 + (2 * x
);
145 fseek(raw
->file
, 512, SEEK_SET
);
146 fread(raw
->rowStart
, 1, x
, raw
->file
);
147 fread(raw
->rowSize
, 1, x
, raw
->file
);
149 ConvertLong(raw
->rowStart
, (long) (x
/sizeof(GLuint
)));
150 ConvertLong((GLuint
*)raw
->rowSize
, (long) (x
/sizeof(GLint
)));
156 static void RawImageClose(rawImageRec
*raw
)
173 static void RawImageGetRow(rawImageRec
*raw
, unsigned char *buf
, int y
, int z
)
175 unsigned char *iPtr
, *oPtr
, pixel
;
178 if ((raw
->type
& 0xFF00) == 0x0100) {
179 fseek(raw
->file
, (long) raw
->rowStart
[y
+z
*raw
->sizeY
], SEEK_SET
);
180 fread(raw
->tmp
, 1, (unsigned int)raw
->rowSize
[y
+z
*raw
->sizeY
],
187 count
= (int)(pixel
& 0x7F);
204 fseek(raw
->file
, 512+(y
*raw
->sizeX
)+(z
*raw
->sizeX
*raw
->sizeY
),
206 fread(buf
, 1, raw
->sizeX
, raw
->file
);
211 static void RawImageGetData(rawImageRec
*raw
, TK_RGBImageRec
*final
)
216 final
->data
= (unsigned char *)malloc((raw
->sizeX
+1)*(raw
->sizeY
+1)*4);
217 if (final
->data
== NULL
) {
218 fprintf(stderr
, "Out of memory!\n");
222 for (i
= 0; i
< (int)(raw
->sizeY
); i
++) {
223 RawImageGetRow(raw
, raw
->tmpR
, i
, 0);
224 RawImageGetRow(raw
, raw
->tmpG
, i
, 1);
225 RawImageGetRow(raw
, raw
->tmpB
, i
, 2);
227 RawImageGetRow(raw
, raw
->tmpA
, i
, 3);
229 for (j
= 0; j
< (int)(raw
->sizeX
); j
++) {
230 *ptr
++ = *(raw
->tmpR
+ j
);
231 *ptr
++ = *(raw
->tmpG
+ j
);
232 *ptr
++ = *(raw
->tmpB
+ j
);
234 *ptr
++ = *(raw
->tmpA
+ j
);
241 static TK_RGBImageRec
*tkRGBImageLoad(const char *fileName
)
244 TK_RGBImageRec
*final
;
246 raw
= RawImageOpen(fileName
);
248 fprintf(stderr
, "File not found\n");
251 final
= (TK_RGBImageRec
*)malloc(sizeof(TK_RGBImageRec
));
253 fprintf(stderr
, "Out of memory!\n");
257 final
->sizeX
= raw
->sizeX
;
258 final
->sizeY
= raw
->sizeY
;
259 final
->components
= raw
->sizeZ
;
260 RawImageGetData(raw
, final
);
266 static void FreeImage( TK_RGBImageRec
*image
)
274 * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
275 * Input: imageFile - name of .rgb to read
276 * intFormat - internal texture format to use, or number of components
277 * Return: GL_TRUE if success, GL_FALSE if error.
279 GLboolean
LoadRGBMipmaps( const char *imageFile
, GLint intFormat
)
282 return LoadRGBMipmaps2( imageFile
, GL_TEXTURE_2D
, intFormat
, &w
, &h
);
287 GLboolean
LoadRGBMipmaps2( const char *imageFile
, GLenum target
,
288 GLint intFormat
, GLint
*width
, GLint
*height
)
292 TK_RGBImageRec
*image
;
294 image
= tkRGBImageLoad( imageFile
);
299 if (image
->components
==3) {
302 else if (image
->components
==4) {
306 /* not implemented */
308 "Error in LoadRGBMipmaps %d-component images not implemented\n",
314 error
= gluBuild2DMipmaps( target
,
316 image
->sizeX
, image
->sizeY
,
321 *width
= image
->sizeX
;
322 *height
= image
->sizeY
;
326 return error
? GL_FALSE
: GL_TRUE
;
332 * Load an SGI .rgb file and return a pointer to the image data.
333 * Input: imageFile - name of .rgb to read
334 * Output: width - width of image
335 * height - height of image
336 * format - format of image (GL_RGB or GL_RGBA)
337 * Return: pointer to image data or NULL if error
339 GLubyte
*LoadRGBImage( const char *imageFile
, GLint
*width
, GLint
*height
,
342 TK_RGBImageRec
*image
;
346 image
= tkRGBImageLoad( imageFile
);
351 if (image
->components
==3) {
354 else if (image
->components
==4) {
358 /* not implemented */
360 "Error in LoadRGBImage %d-component images not implemented\n",
366 *width
= image
->sizeX
;
367 *height
= image
->sizeY
;
369 bytes
= image
->sizeX
* image
->sizeY
* image
->components
;
370 buffer
= (GLubyte
*) malloc(bytes
);
376 memcpy( (void *) buffer
, (void *) image
->data
, bytes
);
383 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
386 static void ConvertRGBtoYUV(GLint w
, GLint h
, GLint texel_bytes
,
392 for (i
= 0; i
< h
; i
++) {
393 for (j
= 0; j
< w
; j
++) {
394 const GLfloat r
= (src
[0]) / 255.0;
395 const GLfloat g
= (src
[1]) / 255.0;
396 const GLfloat b
= (src
[2]) / 255.0;
400 y
= r
* 65.481 + g
* 128.553 + b
* 24.966 + 16;
401 cb
= r
* -37.797 + g
* -74.203 + b
* 112.0 + 128;
402 cr
= r
* 112.0 + g
* -93.786 + b
* -18.214 + 128;
403 /*printf("%f %f %f -> %f %f %f\n", r, g, b, y, cb, cr);*/
404 iy
= (GLint
) CLAMP(y
, 0, 254);
405 icb
= (GLint
) CLAMP(cb
, 0, 254);
406 icr
= (GLint
) CLAMP(cr
, 0, 254);
410 *dest
= (iy
<< 8) | icr
;
414 *dest
= (iy
<< 8) | icb
;
424 * Load an SGI .rgb file and return a pointer to the image data, converted
427 * Input: imageFile - name of .rgb to read
428 * Output: width - width of image
429 * height - height of image
430 * Return: pointer to image data or NULL if error
432 GLushort
*LoadYUVImage( const char *imageFile
, GLint
*width
, GLint
*height
)
434 TK_RGBImageRec
*image
;
437 image
= tkRGBImageLoad( imageFile
);
442 if (image
->components
!= 3 && image
->components
!=4 ) {
443 /* not implemented */
445 "Error in LoadYUVImage %d-component images not implemented\n",
451 *width
= image
->sizeX
;
452 *height
= image
->sizeY
;
454 buffer
= (GLushort
*) malloc( image
->sizeX
* image
->sizeY
* 2 );
457 ConvertRGBtoYUV( image
->sizeX
,