fixed: auto_ptr -> unique_ptr
[opensg.git] / Source / System / Image / FileIO / OSGSGIImageFileType.cpp
blob26cb6e3d48480a6e4306dc998cac124b41d07226
1 /*---------------------------------------------------------------------------*\
2 * OpenSG *
3 * *
4 * *
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
6 * *
7 * www.opensg.org *
8 * *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
10 * *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
13 * License *
14 * *
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
18 * *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
27 * *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
30 * Changes *
31 * *
32 * *
33 * *
34 * *
35 * *
36 * *
37 \*---------------------------------------------------------------------------*/
39 //-------------------------------
40 // Includes
41 //-------------------------------
43 #include <cstdlib>
44 #include <cstdio>
46 #include "OSGConfig.h"
48 #include "OSGBaseFunctions.h"
50 #include <iostream>
51 #include <fstream>
53 #include "OSGLog.h"
55 #include "OSGSGIImageFileType.h"
57 #ifdef OSG_SGI_STL
58 //#include <limits>
59 #ifndef INT_MAX
60 #define INT_MAX numeric_limits<int>::max()
61 #endif
62 #else
63 #include <climits>
64 #endif
66 static const OSG::Char8 *suffixArray[] =
68 "rgb", "rgba", "sgi", "bw", "int", "inta"
71 OSG_BEGIN_NAMESPACE
73 /*! \class SGIImageFileType
75 Image File Type to read/write and store/restore Image objects as
76 SGI data.
78 All the type specific code is included in the class. Does
79 not depend on external libs.
84 /* the basic reader functions */
86 /* I found these on the net a long time ago. They didn't contain any copyright
87 notice and I couldn't find out where I found them.
88 If you wrote them please let us know (info@opensg.org) so that we can either
89 credit you or remove them if you have a problem with us using them.
90 Thanks
91 Dirk
94 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
96 /*! \nohierarchy
99 struct ImageRec
101 unsigned short imagic;
102 unsigned short type;
103 unsigned short dim;
104 unsigned short xsize, ysize, zsize;
105 unsigned int min, max;
106 unsigned int wasteBytes;
107 char name[80];
108 unsigned long colorMap;
109 std::istream *is;
110 std::vector<unsigned char> tmp;
111 std::vector<unsigned int> rowStart;
112 std::vector<unsigned int> rowSize;
114 ImageRec(void) :
115 imagic (0 ),
116 type (0 ),
117 dim (0 ),
118 xsize (0 ),
119 ysize (0 ),
120 zsize (0 ),
121 min (0 ),
122 max (0 ),
123 wasteBytes(0 ),
124 colorMap (0 ),
125 is (NULL),
126 tmp ( ),
127 rowStart ( ),
128 rowSize ( ) {}
130 private:
132 ImageRec(const ImageRec &other);
133 void operator =(const ImageRec &rhs);
136 #endif
138 static void
139 ConvertShort(unsigned short *array, long length)
141 unsigned b1, b2;
142 unsigned char *ptr;
144 ptr = reinterpret_cast<unsigned char *>(array);
145 while (length--)
147 b1 = *ptr++;
148 b2 = *ptr++;
149 *array++ = (b1 << 8) | (b2);
153 static void
154 ConvertLong(unsigned *array, unsigned long length)
156 unsigned long b1, b2, b3, b4;
157 unsigned char *ptr;
159 ptr = reinterpret_cast<unsigned char *>(array);
160 while (length--)
162 b1 = *ptr++;
163 b2 = *ptr++;
164 b3 = *ptr++;
165 b4 = *ptr++;
166 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
170 static bool ImageOpen(ImageRec &image, std::istream &is)
172 image.is = &is;
174 is.read(reinterpret_cast<char*>(&image), 12);
176 if(is.gcount() != 12)
177 return false;
179 bool swapFlag = !osgIsBigEndian();
181 if(swapFlag == true)
182 ConvertShort(&image.imagic, 6);
184 if((image.type & 0xFF00) == 0x0100)
186 is.ignore(512 - 12);
187 if (is.gcount() != 512 - 12)
188 return false;
190 int n = image.ysize * image.zsize;
191 int len = n * sizeof(unsigned);
193 image.rowStart.resize(n);
195 is.read(reinterpret_cast<char*>(&(image.rowStart.front())), len);
197 if(is.gcount() != len)
198 return false;
200 image.rowSize.resize(n);
202 is.read(reinterpret_cast<char*>(&(image.rowSize.front())), len);
204 if(is.gcount() != len)
205 return false;
207 if(swapFlag == true)
209 ConvertLong(&(image.rowStart.front()), n);
210 ConvertLong(&(image.rowSize .front()), n);
212 unsigned int maxSize = 0;
214 for(int i = 0; i < n; ++i)
216 if(image.rowSize[i] > maxSize)
217 maxSize = image.rowSize[i];
220 image.tmp.resize(maxSize);
222 else
224 image.tmp.resize(image.xsize);
227 return true;
230 static bool ImageGetRow(ImageRec &image,
231 unsigned char *buf,
232 int y,
233 int z,
234 int stride)
236 unsigned char *iPtr = &(image.tmp.front());
237 unsigned char *oPtr = buf;
239 if((image.type & 0xFF00) == 0x0100)
241 unsigned int row = y + z * image.ysize;
243 image.is->seekg(image.rowStart[row], std::ios::beg);
245 long len = image.rowSize[row];
247 image.is->read(reinterpret_cast<char*>(iPtr), len);
249 if(image.is->gcount() != len)
250 return false;
252 int npix = image.xsize;
254 while(len > 0)
256 --len;
257 unsigned char pixel = *iPtr++;
258 int count = pixel & 0x7F;
260 if(count == 0)
261 break;
263 if(npix < count)
264 return false;
266 npix -= count;
268 if(pixel & 0x80)
270 if(len < count)
271 return false;
273 len -= count;
275 while(count--)
277 *oPtr = *iPtr++;
278 oPtr += stride;
281 else
283 if(len < 1)
284 return false;
286 --len;
288 pixel = *iPtr++;
290 while(count--)
292 *oPtr = pixel;
293 oPtr += stride;
298 else
300 image.is->seekg(512 + (y + z * image.ysize) * image.xsize,
301 std::ios::beg);
303 image.is->read(reinterpret_cast<char*>(iPtr), image.xsize);
305 if(image.is->gcount() != image.xsize)
306 return false;
308 int count = image.xsize;
310 while(count--)
312 *oPtr = *iPtr++;
313 oPtr += stride;
317 return true;
320 static const UInt32 zsize2pixelformat[] =
322 Image::OSG_L_PF,
323 Image::OSG_LA_PF,
324 Image::OSG_RGB_PF,
325 Image::OSG_RGBA_PF
328 SGIImageFileType SGIImageFileType::_the("image/x-sgi",
329 suffixArray,
330 sizeof(suffixArray));
333 //-------------------------------------------------------------------------
334 /*! Tries to fill the image object with the data read from
335 the given input stream. Returns true on success.
338 bool SGIImageFileType::read( Image *pImage,
339 std::istream &is,
340 const std::string &mimetype)
342 ImageRec img;
344 if(ImageOpen(img, is) == false)
345 return false;
347 if((img.zsize < 1) || (img.zsize > 4))
348 return false;
350 pImage->set(zsize2pixelformat[img.zsize - 1], img.xsize, img.ysize);
352 unsigned char *lptr = pImage->editData();
354 unsigned int lineStride = img.xsize * img.zsize;
356 for(int y = 0; y < img.ysize; ++y)
358 for(int z = 0; z < img.zsize; ++z)
360 if(ImageGetRow(img, lptr + z, y, z, img.zsize) == false)
361 return false;
364 lptr += lineStride;
367 return true;
370 //-------------------------------------------------------------------------
371 /*! Tries to write the image object to the given fileName.
372 Returns true on success.
375 bool SGIImageFileType::write(const Image *pImage,
376 std::ostream &os,
377 const std::string &mimetype)
379 FWARNING(("SGIImageFileType::write: not implemented yet!\n"));
381 return false;
384 bool SGIImageFileType::validateHeader(const Char8 *fileName, bool &implemented)
386 implemented = true;
388 if(fileName == NULL)
389 return false;
391 FILE *file = fopen(fileName, "rb");
393 if(file == NULL)
394 return false;
396 UInt16 magic = 0;
398 fread(static_cast<void *>(&magic), sizeof(magic), 1, file);
400 fclose(file);
402 #if BYTE_ORDER == LITTLE_ENDIAN
403 if(magic == 0xda01) // the magic header is big endian need to swap it.
404 #else
405 if(magic == 0x01da)
406 #endif
408 return true;
411 return false;
414 //-------------------------------------------------------------------------
416 Tries to determine the mime type of the data provided by an input stream
417 by searching for magic bytes. Returns the mime type or an empty string
418 when the function could not determine the mime type.
421 std::string SGIImageFileType::determineMimetypeFromStream(std::istream &is)
423 char filecode[2];
425 is.read(filecode, 2);
426 is.seekg(-2, std::ios::cur);
428 return strncmp(filecode, "\x01\xda", 2) == 0 ?
429 std::string(getMimeType()) : std::string();
432 //-------------------------------------------------------------------------
433 /*! Constructor used for the singleton object
436 SGIImageFileType::SGIImageFileType(const Char8 *mimeType,
437 const Char8 *suffixArray[],
438 UInt16 suffixByteCount) :
440 Inherited(mimeType, suffixArray, suffixByteCount)
444 //-------------------------------------------------------------------------
445 /*! Destructor
448 SGIImageFileType::~SGIImageFileType(void)
452 OSG_END_NAMESPACE