1 /******************************************************************************
2 ** Filename : imageSgi.cpp
5 ** Description : Utility to read SGI image format files. This code was
6 ** originally a SGI image loading utility provided with the
7 ** Mesa 3D library @ http://www.mesa3d.org by Brain Paul.
8 ** This has been extended to read all SGI image formats
9 ** (e.g. INT, INTA, RGB, RGBA).
12 ** Date Name Description
13 ** 06/07/99 BRC Initial Release
17 ** The SGI Image Data (if not RLE)
19 ** If the image is stored verbatim (without RLE), then image data directly
20 ** follows the 512 byte header. The data for each scanline of the first
21 ** channel is written first. If the image has more than 1 channel, all
22 ** the data for the first channel is written, followed by the remaining
23 ** channels. If the BPC value is 1, then each scanline is written as XSIZE
24 ** bytes. If the BPC value is 2, then each scanline is written as XSIZE
25 ** shorts. These shorts are stored in the byte order described above.
27 ******************************************************************************/
28 #define __IMAGESGI_CPP
40 struct sImageSgiHeader header
;
45 unsigned int *rowStart
;
50 static struct sImageSgiRaw
*ImageSgiRawOpen(char const * const fileName
);
51 static void ImageSgiRawClose(struct sImageSgiRaw
*raw
);
52 static void ImageSgiRawGetRow(struct sImageSgiRaw
*raw
, unsigned char *buf
,
54 static void ImageSgiRawGetData(struct sImageSgiRaw
*raw
, struct sImageSgi
56 static void *SwitchEndian16(void *value
);
57 static void *SwitchEndian32(void *value
);
61 unsigned char *mChanTmp
= NULL
;
64 /*****************************************************************************/
65 struct sImageSgi
*ImageSgiOpen(char const * const fileName
)
67 struct sImageSgiRaw
*raw
= NULL
;
68 struct sImageSgi
*final
= NULL
;
70 raw
= ImageSgiRawOpen(fileName
);
71 final
= new struct sImageSgi
;
76 final
->header
= raw
->header
;
78 ImageSgiRawGetData(raw
, final
);
79 ImageSgiRawClose(raw
);
86 /*****************************************************************************/
87 void ImageSgiClose(struct sImageSgi
*image
)
103 /*****************************************************************************/
104 static struct sImageSgiRaw
*ImageSgiRawOpen(char const * const fileName
)
106 struct sImageSgiRaw
*raw
= NULL
;
109 bool swapFlag
= false;
115 endianTest
.testWord
= 1;
117 // Determine endianess of platform.
118 if(endianTest
.testByte
[0] == 1)
123 raw
= new struct sImageSgiRaw
;
132 raw
->rowStart
= NULL
;
134 mFp
= fopen(fileName
, "rb");
137 fread(&raw
->header
, sizeof(struct sImageSgiHeader
), 1, mFp
);
140 SwitchEndian16(&raw
->header
.magic
);
141 SwitchEndian16(&raw
->header
.type
);
142 SwitchEndian16(&raw
->header
.dim
);
143 SwitchEndian16(&raw
->header
.xsize
);
144 SwitchEndian16(&raw
->header
.ysize
);
145 SwitchEndian16(&raw
->header
.zsize
);
148 mChanTmp
= new unsigned char[raw
->header
.xsize
* raw
->header
.ysize
];
150 switch(raw
->header
.zsize
)
153 raw
->chan3
= new unsigned char[raw
->header
.xsize
*
157 raw
->chan2
= new unsigned char[raw
->header
.xsize
*
161 raw
->chan1
= new unsigned char[raw
->header
.xsize
*
165 raw
->chan0
= new unsigned char[raw
->header
.xsize
*
170 if(raw
->header
.type
== IMAGE_SGI_TYPE_RLE
)
172 x
= raw
->header
.ysize
* raw
->header
.zsize
* sizeof(unsigned int);
173 raw
->rowStart
= new unsigned int[x
];
174 raw
->rowSize
= new int[x
];
176 fseek(mFp
, sizeof(struct sImageSgiHeader
), SEEK_SET
);
177 fread(raw
->rowStart
, 1, x
, mFp
);
178 fread(raw
->rowSize
, 1, x
, mFp
);
182 for(i
=0; i
<x
/sizeof(unsigned int); i
++)
183 SwitchEndian32(&raw
->rowStart
[i
]);
184 for(i
=0; i
<x
/sizeof(int); i
++)
185 SwitchEndian32(&raw
->rowSize
[i
]);
196 /*****************************************************************************/
197 static void ImageSgiRawClose(struct sImageSgiRaw
*raw
)
228 } // ImageSgiRawClose
231 /*****************************************************************************/
232 static void ImageSgiRawGetRow(struct sImageSgiRaw
*raw
, unsigned char *buf
,
235 unsigned char *iPtr
= NULL
;
236 unsigned char *oPtr
= NULL
;
240 if((raw
->header
.type
& 0xFF00) == 0x0100)
242 fseek(mFp
, raw
->rowStart
[y
+z
*raw
->header
.ysize
], SEEK_SET
);
243 fread(mChanTmp
, 1, (unsigned int)raw
->rowSize
[y
+z
*raw
->header
.ysize
],
250 count
= (int)(pixel
& 0x7F);
275 sizeof(struct sImageSgiHeader
)+(y
*raw
->header
.xsize
) +
276 (z
*raw
->header
.xsize
*raw
->header
.ysize
),
278 fread(buf
, 1, raw
->header
.xsize
, mFp
);
282 } // ImageSgiRawGetRow
285 /*****************************************************************************/
286 static void ImageSgiRawGetData(struct sImageSgiRaw
*raw
, struct sImageSgi
289 unsigned char *ptr
= NULL
;
294 char[raw
->header
.xsize
*raw
->header
.ysize
*raw
->header
.zsize
];
298 for(i
=0; i
<raw
->header
.ysize
; i
++)
300 switch(raw
->header
.zsize
)
303 ImageSgiRawGetRow(raw
, raw
->chan0
, i
, 0);
304 for(j
=0; j
<raw
->header
.xsize
; j
++)
305 *(ptr
++) = raw
->chan0
[j
];
308 ImageSgiRawGetRow(raw
, raw
->chan0
, i
, 0);
309 ImageSgiRawGetRow(raw
, raw
->chan1
, i
, 1);
310 for(j
=0; j
<raw
->header
.xsize
; j
++)
312 *(ptr
++) = raw
->chan0
[j
];
313 *(ptr
++) = raw
->chan1
[j
];
317 ImageSgiRawGetRow(raw
, raw
->chan0
, i
, 0);
318 ImageSgiRawGetRow(raw
, raw
->chan1
, i
, 1);
319 ImageSgiRawGetRow(raw
, raw
->chan2
, i
, 2);
320 for(j
=0; j
<raw
->header
.xsize
; j
++)
322 *(ptr
++) = raw
->chan0
[j
];
323 *(ptr
++) = raw
->chan1
[j
];
324 *(ptr
++) = raw
->chan2
[j
];
328 ImageSgiRawGetRow(raw
, raw
->chan0
, i
, 0);
329 ImageSgiRawGetRow(raw
, raw
->chan1
, i
, 1);
330 ImageSgiRawGetRow(raw
, raw
->chan2
, i
, 2);
331 ImageSgiRawGetRow(raw
, raw
->chan3
, i
, 3);
332 for(j
=0; j
<raw
->header
.xsize
; j
++)
334 *(ptr
++) = raw
->chan0
[j
];
335 *(ptr
++) = raw
->chan1
[j
];
336 *(ptr
++) = raw
->chan2
[j
];
337 *(ptr
++) = raw
->chan3
[j
];
344 } // ImageSgiRawGetData
347 /*****************************************************************************/
348 static void *SwitchEndian16(void *value
)
350 short value16
= *(short *) value
;
351 value16
= ((value16
& 0xff00) >> 8L) +
352 ((value16
& 0x00ff) << 8L);
353 *(short *)value
= value16
;
358 /*****************************************************************************/
359 static void *SwitchEndian32(void *value
)
361 int value32
= *(int *) value
;
362 value32
= ((value32
& 0xff000000) >> 24L) +
363 ((value32
& 0x00ff0000) >> 8) +
364 ((value32
& 0x0000ff00) << 8) +
365 ((value32
& 0x000000ff) << 24L);
366 *(int *)value
= value32
;