00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045
00046 #include "OSGConfig.h"
00047
00048 #include "OSGBaseFunctions.h"
00049
00050 #include <iostream>
00051 #include <vector>
00052
00053 #include <OSGLog.h>
00054
00055 #include "OSGSGIImageFileType.h"
00056
00057 #ifdef OSG_SGI_STL
00058
00059 #ifndef INT_MAX
00060 #define INT_MAX numeric_limits<int>::max()
00061 #endif
00062 #else
00063 #include <limits.h>
00064 #endif
00065
00066 OSG_USING_NAMESPACE
00067
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 #if !defined(OSG_DO_DOC) || defined(OSG_DOC_DEV)
00091
00095 struct ImageRec
00096 {
00097 unsigned short imagic;
00098 unsigned short type;
00099 unsigned short dim;
00100 unsigned short xsize, ysize, zsize;
00101 unsigned int min, max;
00102 unsigned int wasteBytes;
00103 char name[80];
00104 unsigned long colorMap;
00105 std::istream *is;
00106 std::vector<unsigned char> tmp;
00107 std::vector<unsigned int> rowStart;
00108 std::vector<unsigned int> rowSize;
00109 };
00110
00111 #endif
00112
00113 static void
00114 ConvertShort(unsigned short *array, long length)
00115 {
00116 unsigned b1, b2;
00117 unsigned char *ptr;
00118
00119 ptr = (unsigned char *)array;
00120 while (length--)
00121 {
00122 b1 = *ptr++;
00123 b2 = *ptr++;
00124 *array++ = (b1 << 8) | (b2);
00125 }
00126 }
00127
00128 static void
00129 ConvertLong(unsigned *array, unsigned long length)
00130 {
00131 unsigned long b1, b2, b3, b4;
00132 unsigned char *ptr;
00133
00134 ptr = (unsigned char *)array;
00135 while (length--)
00136 {
00137 b1 = *ptr++;
00138 b2 = *ptr++;
00139 b3 = *ptr++;
00140 b4 = *ptr++;
00141 *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
00142 }
00143 }
00144
00145 static bool ImageOpen(ImageRec &image, std::istream &is)
00146 {
00147 image.is = &is;
00148
00149 is.read(reinterpret_cast<char*>(&image), 12);
00150 if (is.gcount() != 12)
00151 return false;
00152
00153 bool swapFlag = !osgIsBigEndian();
00154 if (swapFlag == true)
00155 ConvertShort(&image.imagic, 6);
00156
00157 if ((image.type & 0xFF00) == 0x0100)
00158 {
00159 is.ignore(512 - 12);
00160 if (is.gcount() != 512 - 12)
00161 return false;
00162 int n = image.ysize * image.zsize;
00163 int len = n * sizeof(unsigned);
00164 image.rowStart.resize(n);
00165 is.read(reinterpret_cast<char*>(&(image.rowStart.front())), len);
00166 if (is.gcount() != len)
00167 return false;
00168 image.rowSize.resize(n);
00169 is.read(reinterpret_cast<char*>(&(image.rowSize.front())), len);
00170 if (is.gcount() != len)
00171 return false;
00172 if (swapFlag == true)
00173 {
00174 ConvertLong(&(image.rowStart.front()), n);
00175 ConvertLong(&(image.rowSize.front()), n);
00176 }
00177 unsigned int maxSize = 0;
00178 for (int i = 0; i < n; ++i)
00179 if (image.rowSize[i] > maxSize)
00180 maxSize = image.rowSize[i];
00181 image.tmp.resize(maxSize);
00182 }
00183 else
00184 image.tmp.resize(image.xsize);
00185 return true;
00186 }
00187
00188 static bool ImageGetRow(ImageRec &image, unsigned char *buf, int y, int z, int stride)
00189 {
00190 unsigned char *iPtr = &(image.tmp.front());
00191 unsigned char *oPtr = buf;
00192 if ((image.type & 0xFF00) == 0x0100)
00193 {
00194 unsigned int row = y + z * image.ysize;
00195 image.is->seekg(image.rowStart[row], std::ios::beg);
00196 long len = image.rowSize[row];
00197 image.is->read(reinterpret_cast<char*>(iPtr), len);
00198 if (image.is->gcount() != len)
00199 return false;
00200
00201 int npix = image.xsize;
00202 while (len > 0)
00203 {
00204 --len;
00205 unsigned char pixel = *iPtr++;
00206 int count = pixel & 0x7F;
00207 if (count == 0)
00208 break;
00209 if (npix < count)
00210 return false;
00211 npix -= count;
00212 if (pixel & 0x80)
00213 {
00214 if (len < count)
00215 return false;
00216 len -= count;
00217 while (count--)
00218 {
00219 *oPtr = *iPtr++;
00220 oPtr += stride;
00221 }
00222 }
00223 else
00224 {
00225 if (len < 1)
00226 return false;
00227 --len;
00228 pixel = *iPtr++;
00229 while (count--)
00230 {
00231 *oPtr = pixel;
00232 oPtr += stride;
00233 }
00234 }
00235 }
00236 }
00237 else
00238 {
00239 image.is->seekg(512 + (y + z * image.ysize) * image.xsize, std::ios::beg);
00240 image.is->read(reinterpret_cast<char*>(iPtr), image.xsize);
00241 if (image.is->gcount() != image.xsize)
00242 return false;
00243 int count = image.xsize;
00244 while (count--)
00245 {
00246 *oPtr = *iPtr++;
00247 oPtr += stride;
00248 }
00249 }
00250 return true;
00251 }
00252
00253 static const UInt32 zsize2pixelformat[] =
00254 {
00255 Image::OSG_L_PF,
00256 Image::OSG_LA_PF,
00257 Image::OSG_RGB_PF,
00258 Image::OSG_RGBA_PF
00259 };
00260
00261
00262
00263
00264
00265
00266 static const Char8 *suffixArray[] =
00267 {
00268 "rgb", "rgba", "sgi", "bw"
00269 };
00270
00271 SGIImageFileType SGIImageFileType::_the ( "image/x-sgi",
00272 suffixArray,
00273 sizeof(suffixArray) );
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00289 SGIImageFileType& SGIImageFileType::the (void)
00290 {
00291 return _the;
00292 }
00293
00294
00295
00296
00297
00298
00303 bool SGIImageFileType::read (ImagePtr &image, std::istream &is, const std::string &mimetype)
00304 {
00305 ImageRec img;
00306 if (ImageOpen(img, is) == false)
00307 return false;
00308
00309 if ((img.zsize < 1) || (img.zsize > 4))
00310 return false;
00311
00312 image->set(zsize2pixelformat[img.zsize - 1], img.xsize, img.ysize);
00313 unsigned char *lptr = image->getData();
00314 unsigned int lineStride = img.xsize * img.zsize;
00315 for (int y = 0; y < img.ysize; ++y)
00316 {
00317 for (int z = 0; z < img.zsize; ++z)
00318 if (ImageGetRow(img, lptr + z, y, z, img.zsize) == false)
00319 return false;
00320 lptr += lineStride;
00321 }
00322
00323 return true;
00324 }
00325
00326
00332 std::string SGIImageFileType::determineMimetypeFromStream(std::istream &is)
00333 {
00334 char filecode[2];
00335 is.read(filecode, 2);
00336 is.seekg(-2, std::ios::cur);
00337 return strncmp(filecode, "\x01\xda", 2) == 0 ?
00338 std::string(getMimeType()) : std::string();
00339 }
00340
00341
00342
00343 bool SGIImageFileType::validateHeader( const Char8 *fileName, bool &implemented )
00344 {
00345 implemented = true;
00346
00347 if(fileName == NULL)
00348 return false;
00349
00350 FILE *file = fopen(fileName, "rb");
00351 if(file == NULL)
00352 return false;
00353
00354 UInt16 magic = 0;
00355 fread((void *) &magic, sizeof(magic), 1, file);
00356 fclose(file);
00357
00358 #if BYTE_ORDER == LITTLE_ENDIAN
00359 if(magic == 0xda01)
00360 #else
00361 if(magic == 0x01da)
00362 #endif
00363 {
00364 return true;
00365 }
00366
00367 return false;
00368 }
00369
00370
00374 SGIImageFileType::SGIImageFileType ( const Char8 *mimeType,
00375 const Char8 *suffixArray[],
00376 UInt16 suffixByteCount )
00377 : ImageFileType ( mimeType, suffixArray, suffixByteCount )
00378 {}
00379
00380
00384 SGIImageFileType::~SGIImageFileType (void) {}