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 #include <stdlib.h>
00042 #include <stdio.h>
00043
00044 #include "OSGConfig.h"
00045
00046 #include <vector>
00047 #include <string>
00048
00049 #include <iostream>
00050
00051 #include <OSGLog.h>
00052
00053 #include "OSGNRRDImageFileType.h"
00054
00055 #ifdef OSG_SGI_STL
00056
00057
00058 #ifndef INT_MAX
00059 #define INT_MAX numeric_limits<int>::max()
00060 #endif
00061 #else
00062 #include <limits.h>
00063 #endif
00064 OSG_USING_NAMESPACE
00065
00066
00079
00080
00081
00082
00083 static const Char8 *suffixArray[] =
00084 {
00085 "nrrd"
00086 };
00087
00088
00089 NRRDImageFileType NRRDImageFileType::_the("image/x-nrrd",
00090 suffixArray, sizeof(suffixArray),
00091 OSG_READ_SUPPORTED |
00092 OSG_WRITE_SUPPORTED);
00093
00094
00095
00096
00097
00098 enum HeadElem {
00099 INVALID_HE,
00100 MIME_HE,
00101 TYPE_HE,
00102 DIMENSION_HE,
00103 SIZES_HE,
00104 ENDIAN_HE,
00105 ENCODING_HE,
00106
00107 UNSIGNED_HE,
00108 SIGNED_HE,
00109
00110 LITTLE_HE,
00111 BIG_HE,
00112
00113 RAW_HE,
00114 ASCII_HE,
00115
00116 CHAR_HE,
00117 SHORT_HE,
00118 };
00119
00120 struct HeadStr {
00121 std::string str;
00122 HeadElem headElem;
00123 };
00124
00125 static HeadStr headStrVec[] = {
00126 { "NRRD0001", MIME_HE },
00127 { "type", TYPE_HE },
00128 { "dimension", DIMENSION_HE },
00129 { "sizes", SIZES_HE },
00130 { "endian", ENDIAN_HE },
00131 { "encoding", ENCODING_HE },
00132
00133 { "unsigned", UNSIGNED_HE },
00134 { "signed", SIGNED_HE },
00135
00136 { "char", CHAR_HE },
00137 { "short", SHORT_HE },
00138
00139 { "", INVALID_HE }
00140 };
00141
00142 inline HeadElem mapElem (const std::string & str )
00143 {
00144 unsigned i = 0;
00145
00146 for ( i = 0; headStrVec[i].headElem != INVALID_HE; ++i )
00147 if (headStrVec[i].str == str)
00148 break;
00149
00150 return headStrVec[i].headElem;
00151 }
00152
00153 inline unsigned stringTokenizer( const std::string& str,
00154 std::vector<std::string>& tokens,
00155 const std::string& delimiters = " ")
00156 {
00157
00158 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
00159
00160 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
00161
00162 while (std::string::npos != pos || std::string::npos != lastPos)
00163 {
00164
00165 tokens.push_back(str.substr(lastPos, pos - lastPos));
00166
00167 lastPos = str.find_first_not_of(delimiters, pos);
00168
00169 pos = str.find_first_of(delimiters, lastPos);
00170 }
00171
00172 return tokens.size();
00173 }
00174
00175
00176
00177
00178
00179
00183 NRRDImageFileType& NRRDImageFileType::the (void)
00184 {
00185 return _the;
00186 }
00187
00188
00189
00190
00191
00192
00197 bool NRRDImageFileType::read(ImagePtr &image, std::istream &in, const std::string &mimetype)
00198 {
00199 bool retCode = false;
00200 bool isSigned = false, littleEndian = true, rawEncoding = true;
00201 int width = 1, height = 1, depth = 1, dimension = 3, channel = 1;
00202 HeadElem dataType = INVALID_HE;
00203 unsigned i, n, m;
00204 UChar8 *data = 0;
00205 std::string line;
00206 std::vector < std::string > tokenVec;
00207 bool inHead;
00208 osg::Image::PixelFormat pixelFormat;
00209 osg::Image::Type imageType;
00210
00211 if (in.good()) {
00212 for (inHead = true; inHead;) {
00213 std::getline(in,line);
00214 tokenVec.clear();
00215 if ((n = stringTokenizer (line, tokenVec, ": \n"))) {
00216 switch (mapElem(tokenVec[0])){
00217 case TYPE_HE:
00218 switch (n) {
00219 case 2:
00220 dataType = mapElem(tokenVec[1]);
00221 break;
00222 case 3:
00223 isSigned = (mapElem(tokenVec[1]) == SIGNED_HE);
00224 dataType = mapElem(tokenVec[2]);
00225 break;
00226 default:
00227 FFATAL (( "Invalid %s/%d in NRRD header\n",
00228 tokenVec[0].c_str(), n ));
00229 break;
00230 }
00231 break;
00232 case DIMENSION_HE:
00233 switch (n) {
00234 case 2:
00235 dimension = atoi(tokenVec[1].c_str());
00236 break;
00237 default:
00238 FFATAL (( "Invalid %s/%d in NRRD header\n",
00239 tokenVec[0].c_str(), n ));
00240 break;
00241 }
00242 break;
00243 case SIZES_HE:
00244 switch (n) {
00245 case 5:
00246 channel = atoi(tokenVec[1].c_str());
00247 width = atoi(tokenVec[2].c_str());
00248 height = atoi(tokenVec[3].c_str());
00249 depth = atoi(tokenVec[4].c_str());
00250 break;
00251 case 4:
00252 width = atoi(tokenVec[1].c_str());
00253 height = atoi(tokenVec[2].c_str());
00254 depth = atoi(tokenVec[3].c_str());
00255 break;
00256 case 3:
00257 width = atoi(tokenVec[1].c_str());
00258 height = atoi(tokenVec[2].c_str());
00259 depth = 1;
00260 break;
00261 case 2:
00262 width = atoi(tokenVec[1].c_str());
00263 height = 1;
00264 depth = 1;
00265 break;
00266 default:
00267 FFATAL (( "Invalid %s/%d in NRRD header\n",
00268 tokenVec[0].c_str(), n ));
00269 break;
00270 }
00271 if ((n <= 4) && (width <= 4))
00272 {
00273 channel = width;
00274 width = height;
00275 height = depth;
00276 depth = 1;
00277 }
00278 break;
00279 case ENDIAN_HE:
00280 switch (n) {
00281 case 2:
00282 littleEndian = (mapElem(tokenVec[1]) == LITTLE_HE);
00283 break;
00284 default:
00285 FFATAL (( "Invalid %s/%d in NRRD header\n",
00286 tokenVec[0].c_str(), n ));
00287 break;
00288 }
00289 break;
00290 case ENCODING_HE:
00291 switch (n) {
00292 case 2:
00293 rawEncoding = (mapElem(tokenVec[1]) == RAW_HE);
00294 break;
00295 default:
00296 FFATAL (( "Invalid %s/%d in NRRD header\n",
00297 tokenVec[0].c_str(), n ));
00298 break;
00299 }
00300 break;
00301 default:
00302 break;
00303 }
00304 }
00305 else
00306 inHead = false;
00307 }
00308
00309 switch (dataType) {
00310 case SHORT_HE:
00311 imageType = osg::Image::OSG_UINT16_IMAGEDATA;
00312 break;
00313 default:
00314 imageType = osg::Image::OSG_UINT8_IMAGEDATA;
00315 break;
00316 }
00317
00318 switch (channel) {
00319 case 4:
00320 pixelFormat = osg::Image::OSG_RGBA_PF;
00321 break;
00322 case 3:
00323 pixelFormat = osg::Image::OSG_RGB_PF;
00324 break;
00325 case 2:
00326 pixelFormat = osg::Image::OSG_LA_PF;
00327 break;
00328 default:
00329 pixelFormat = osg::Image::OSG_L_PF;
00330 break;
00331 }
00332
00333 if (isSigned) {
00334 FFATAL (( "Read signed data not supported\n" ));
00335 }
00336
00337 FINFO(("NRRDImageFileType::read: got %d D %s endian %s data.\n",
00338 dimension, littleEndian?"little":"big",
00339 rawEncoding?"raw":"cooked"));
00340
00341 image->set ( pixelFormat, width, height, depth,
00342 1, 1, 0.0, 0, imageType );
00343
00344 n = image->getSize();
00345 data = image->getData();
00346
00347 in.read ((char*)(data), n);
00348
00349 retCode = true;
00350 }
00351
00352 return retCode;
00353 }
00354
00355
00359 NRRDImageFileType::NRRDImageFileType(const Char8 *mimeType,
00360 const Char8 *suffixArray[],
00361 UInt16 suffixByteCount,
00362 UInt32 flags) :
00363 ImageFileType(mimeType, suffixArray, suffixByteCount, flags)
00364 {}
00365
00366
00370 NRRDImageFileType::~NRRDImageFileType(void) {}