/[projet1]/public/pc/shared_libraries/freeimage/v3.12.0/Source/FreeImage/PluginSGI.cpp
Defence Force logotype

Contents of /public/pc/shared_libraries/freeimage/v3.12.0/Source/FreeImage/PluginSGI.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 126 - (show annotations)
Mon Jul 13 12:20:10 2009 UTC (10 years, 7 months ago) by dbug
File size: 11099 byte(s)
Added some shared libraries (UnitTest++, and FreeImage) to avoid having every single project brings its own libraries.
Ideally people should add them in a way we can upgrade versions without breaking things:
-> public/pc/shared_libraries/library_name/library_version/actuall_content
1 // ==========================================================
2 // SGI Loader
3 //
4 // Design and implementation by
5 // - Sherman Wilcox
6 // - Noam Gat
7 //
8 // References :
9 // ------------
10 // - The SGI Image File Format, Version 1.0
11 // http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/sgiversion.html
12 // - SGI RGB Image Format
13 // http://astronomy.swin.edu.au/~pbourke/dataformats/sgirgb/
14 //
15 //
16 // This file is part of FreeImage 3
17 //
18 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
19 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
20 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
21 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
22 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
23 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
24 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
25 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
26 // THIS DISCLAIMER.
27 //
28 // Use at your own risk!
29 // ==========================================================
30
31 #include "FreeImage.h"
32 #include "Utilities.h"
33
34 // ----------------------------------------------------------
35 // Constants + headers
36 // ----------------------------------------------------------
37
38 #ifdef _WIN32
39 #pragma pack(push, 1)
40 #else
41 #pragma pack(1)
42 #endif
43
44 typedef struct tagSGIHeader {
45 /** IRIS image file magic number. This should be decimal 474. */
46 WORD magic;
47 /** Storage format: 0 for uncompressed, 1 for RLE compression. */
48 BYTE storage;
49 /** Number of bytes per pixel channel. Legally 1 or 2. */
50 BYTE bpc;
51 /**
52 Number of dimensions. Legally 1, 2, or 3.
53 1 means a single row, XSIZE long
54 2 means a single 2D image
55 3 means multiple 2D images
56 */
57 WORD dimension;
58 /** X size in pixels */
59 WORD xsize;
60 /** Y size in pixels */
61 WORD ysize;
62 /**
63 Number of channels.
64 1 indicates greyscale
65 3 indicates RGB
66 4 indicates RGB and Alpha
67 */
68 WORD zsize;
69 /** Minimum pixel value. This is the lowest pixel value in the image.*/
70 LONG pixmin;
71 /** Maximum pixel value. This is the highest pixel value in the image.*/
72 LONG pixmax;
73 /** Ignored. Normally set to 0. */
74 char dummy[4];
75 /** Image name. Must be null terminated, therefore at most 79 bytes. */
76 char imagename[80];
77 /**
78 Colormap ID.
79 0 - normal mode
80 1 - dithered, 3 mits for red and green, 2 for blue, obsolete
81 2 - index colour, obsolete
82 3 - not an image but a colourmap
83 */
84 LONG colormap;
85 /** Ignored. Should be set to 0, makes the header 512 bytes. */
86 char reserved[404];
87 } SGIHeader;
88
89 typedef struct tagRLEStatus {
90 int cnt;
91 int val;
92 } RLEStatus;
93
94 #ifdef _WIN32
95 #pragma pack(pop)
96 #else
97 #pragma pack()
98 #endif
99
100 static const char *SGI_BAD_MALLOC = "Out of memory";
101 static const char *SGI_LESS_THAN_HEADER_LENGTH = "Incorrect header size";
102 static const char *SGI_BAD_MAGIC_NUMBER = "Bad magic number";
103 static const char *SGI_16_BIT_COMPONENTS_NOT_SUPPORTED = "No 16 bit support";
104 static const char *SGI_COLORMAPS_NOT_SUPPORTED = "No colormap support";
105 static const char *SGI_EOF_IN_RLE_INDEX = "EOF in run length encoding";
106 static const char *SGI_EOF_IN_IMAGE_DATA = "EOF in image data";
107 static const char *SGI_INVALID_CHANNEL_COUNT = "Invalid channel count";
108
109 // ==========================================================
110 // Plugin Interface
111 // ==========================================================
112
113 static int s_format_id;
114
115 // ==========================================================
116 // Plugin Implementation
117 // ==========================================================
118
119 #ifndef FREEIMAGE_BIGENDIAN
120 static void
121 SwapHeader(SGIHeader *header) {
122 SwapShort(&header->magic);
123 SwapShort(&header->dimension);
124 SwapShort(&header->xsize);
125 SwapShort(&header->ysize);
126 SwapShort(&header->zsize);
127 SwapLong((DWORD*)&header->pixmin);
128 SwapLong((DWORD*)&header->pixmax);
129 SwapLong((DWORD*)&header->colormap);
130 }
131 #endif
132
133 static int
134 get_rlechar(FreeImageIO *io, fi_handle handle, RLEStatus *pstatus) {
135 if (!pstatus->cnt) {
136 int cnt = 0;
137 while (0 == cnt) {
138 BYTE packed = 0;
139 if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
140 return EOF;
141 }
142 cnt = packed;
143 }
144 if (cnt == EOF) {
145 return EOF;
146 }
147 pstatus->cnt = cnt & 0x7F;
148 if (cnt & 0x80) {
149 pstatus->val = -1;
150 } else {
151 BYTE packed = 0;
152 if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
153 return EOF;
154 }
155 pstatus->val = packed;
156 }
157 }
158 pstatus->cnt--;
159 if (pstatus->val == -1) {
160 BYTE packed = 0;
161 if(io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1) {
162 return EOF;
163 }
164 return packed;
165 }
166 else {
167 return pstatus->val;
168 }
169 }
170
171 static const char * DLL_CALLCONV
172 Format() {
173 return "SGI";
174 }
175
176 static const char * DLL_CALLCONV
177 Description() {
178 return "SGI Image Format";
179 }
180
181 static const char * DLL_CALLCONV
182 Extension() {
183 return "sgi";
184 }
185
186 static const char * DLL_CALLCONV
187 RegExpr() {
188 return NULL;
189 }
190
191 static const char * DLL_CALLCONV
192 MimeType() {
193 return "image/sgi";
194 }
195
196 static BOOL DLL_CALLCONV
197 Validate(FreeImageIO *io, fi_handle handle) {
198 BYTE sgi_signature[2] = { 0x01, 0xDA };
199 BYTE signature[2] = { 0, 0 };
200
201 io->read_proc(signature, 1, sizeof(sgi_signature), handle);
202
203 return (memcmp(sgi_signature, signature, sizeof(sgi_signature)) == 0);
204 }
205
206 static BOOL DLL_CALLCONV
207 SupportsExportDepth(int depth) {
208 return FALSE;
209 }
210
211 static BOOL DLL_CALLCONV
212 SupportsExportType(FREE_IMAGE_TYPE type) {
213 return FALSE;
214 }
215
216 static FIBITMAP * DLL_CALLCONV
217 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
218 int width = 0, height = 0, zsize = 0;
219 int i, dim;
220 int bitcount;
221 SGIHeader sgiHeader;
222 RLEStatus my_rle_status;
223 FIBITMAP *dib = NULL;
224 LONG *pRowIndex = NULL;
225
226 try {
227 // read the header
228 memset(&sgiHeader, 0, sizeof(SGIHeader));
229 if(io->read_proc(&sgiHeader, 1, sizeof(SGIHeader), handle) < sizeof(SGIHeader)) {
230 throw SGI_LESS_THAN_HEADER_LENGTH;
231 }
232 #ifndef FREEIMAGE_BIGENDIAN
233 SwapHeader(&sgiHeader);
234 #endif
235 if(sgiHeader.magic != 474) {
236 throw SGI_BAD_MAGIC_NUMBER;
237 }
238
239 BOOL bIsRLE = (sgiHeader.storage == 1) ? TRUE : FALSE;
240
241 // check for unsupported image types
242 if (sgiHeader.bpc != 1) {
243 // Expected one byte per color component
244 throw SGI_16_BIT_COMPONENTS_NOT_SUPPORTED;
245 }
246 if (sgiHeader.colormap != 0) {
247 // Indexed or dithered images not supported
248 throw SGI_COLORMAPS_NOT_SUPPORTED;
249 }
250
251 // get the width & height
252 dim = sgiHeader.dimension;
253 width = sgiHeader.xsize;
254 if (dim < 3) {
255 zsize = 1;
256 } else {
257 zsize = sgiHeader.zsize;
258 }
259
260 if (dim < 2) {
261 height = 1;
262 } else {
263 height = sgiHeader.ysize;
264 }
265
266 if(bIsRLE) {
267 // read the Offset Tables
268 int index_len = height * zsize;
269 pRowIndex = (LONG*)malloc(index_len * sizeof(LONG));
270 if(!pRowIndex) {
271 throw SGI_BAD_MALLOC;
272 }
273
274 if ((unsigned)index_len != io->read_proc(pRowIndex, sizeof(LONG), index_len, handle)) {
275 throw SGI_EOF_IN_RLE_INDEX;
276 }
277
278 #ifndef FREEIMAGE_BIGENDIAN
279 // Fix byte order in index
280 for (i = 0; i < index_len; i++) {
281 SwapLong((DWORD*)&pRowIndex[i]);
282 }
283 #endif
284 // Discard row size index
285 for (i = 0; i < (int)(index_len * sizeof(LONG)); i++) {
286 BYTE packed = 0;
287 if( io->read_proc(&packed, sizeof(BYTE), 1, handle) < 1 ) {
288 throw SGI_EOF_IN_RLE_INDEX;
289 }
290 }
291 }
292
293 switch(zsize) {
294 case 1:
295 bitcount = 8;
296 break;
297 case 2:
298 //Grayscale+Alpha. Need to fake RGBA
299 bitcount = 32;
300 break;
301 case 3:
302 bitcount = 24;
303 break;
304 case 4:
305 bitcount = 32;
306 break;
307 default:
308 throw SGI_INVALID_CHANNEL_COUNT;
309 }
310
311 dib = FreeImage_Allocate(width, height, bitcount);
312 if(!dib) {
313 throw SGI_BAD_MALLOC;
314 }
315
316 if (bitcount == 8) {
317 // 8-bit SGI files are grayscale images, so we'll generate
318 // a grayscale palette.
319 RGBQUAD *pclrs = FreeImage_GetPalette(dib);
320 for (i = 0; i < 256; i++) {
321 pclrs[i].rgbRed = (BYTE)i;
322 pclrs[i].rgbGreen = (BYTE)i;
323 pclrs[i].rgbBlue = (BYTE)i;
324 pclrs[i].rgbReserved = 0;
325 }
326 }
327
328 // decode the image
329
330 memset(&my_rle_status, 0, sizeof(RLEStatus));
331
332 int ns = FreeImage_GetPitch(dib);
333 BYTE *pStartRow = FreeImage_GetScanLine(dib, 0);
334 int offset_table[] = { 2, 1, 0, 3 };
335 int numChannels = zsize;
336 if (zsize < 3) {
337 offset_table[0] = 0;
338 }
339 if (zsize == 2)
340 {
341 //This is how faked grayscale+alpha works.
342 //First channel goes into first
343 //second channel goes into alpha (4th channel)
344 //Two channels are left empty and will be copied later
345 offset_table[1] = 3;
346 numChannels = 4;
347 }
348
349 LONG *pri = pRowIndex;
350 for (i = 0; i < zsize; i++) {
351 BYTE *pRow = pStartRow + offset_table[i];
352 for (int j = 0; j < height; j++, pRow += ns, pri++) {
353 BYTE *p = pRow;
354 if (bIsRLE) {
355 my_rle_status.cnt = 0;
356 io->seek_proc(handle, *pri, SEEK_SET);
357 }
358 for (int k = 0; k < width; k++, p += numChannels) {
359 int ch;
360 BYTE packed = 0;
361 if (bIsRLE) {
362 ch = get_rlechar(io, handle, &my_rle_status);
363 packed = (BYTE)ch;
364 }
365 else {
366 ch = io->read_proc(&packed, sizeof(BYTE), 1, handle);
367 }
368 if (ch == EOF) {
369 throw SGI_EOF_IN_IMAGE_DATA;
370 }
371 *p = packed;
372 }
373 }
374 }
375
376 if (zsize == 2)
377 {
378 BYTE *pRow = pStartRow;
379 //If faking RGBA from grayscale + alpha, copy first channel to second and third
380 for (int i=0; i<height; i++, pRow += ns)
381 {
382 BYTE *pPixel = pRow;
383 for (int j=0; j<width; j++)
384 {
385 pPixel[2] = pPixel[1] = pPixel[0];
386 pPixel += 4;
387 }
388 }
389 }
390 if(pRowIndex)
391 free(pRowIndex);
392
393 return dib;
394
395 } catch(const char *text) {
396 if(pRowIndex) free(pRowIndex);
397 if(dib) FreeImage_Unload(dib);
398 FreeImage_OutputMessageProc(s_format_id, text);
399 return NULL;
400 }
401 }
402
403 // ==========================================================
404 // Init
405 // ==========================================================
406
407 void DLL_CALLCONV
408 InitSGI(Plugin *plugin, int format_id) {
409 s_format_id = format_id;
410
411 plugin->format_proc = Format;
412 plugin->description_proc = Description;
413 plugin->extension_proc = Extension;
414 plugin->regexpr_proc = RegExpr;
415 plugin->open_proc = NULL;
416 plugin->close_proc = NULL;
417 plugin->pagecount_proc = NULL;
418 plugin->pagecapability_proc = NULL;
419 plugin->load_proc = Load;
420 plugin->save_proc = NULL;
421 plugin->validate_proc = Validate;
422 plugin->mime_proc = MimeType;
423 plugin->supports_export_bpp_proc = SupportsExportDepth;
424 plugin->supports_export_type_proc = SupportsExportType;
425 plugin->supports_icc_profiles_proc = NULL;
426 }
427

  ViewVC Help
Powered by ViewVC 1.1.26