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 #include "Raster/PnmParser.H"
00039
00040 #include "Util/Assert.H"
00041 #include "Image/Image.H"
00042 #include "Image/Pixels.H"
00043 #include "Raster/GenericFrame.H"
00044 #include "Util/Assert.H"
00045 #include "Util/FileUtil.H"
00046 #include "Util/log.H"
00047 #include "rutz/shared_ptr.h"
00048
00049 #include <cctype>
00050 #include <istream>
00051 #include <limits>
00052 #include <string>
00053
00054
00055 struct PnmParser::Rep
00056 {
00057 Rep(const std::string& fname_) :
00058 fname(fname_),
00059 owned_strm(openMaybeCompressedFile(fname_)),
00060 strm(0),
00061 mode(-1),
00062 w(-1),
00063 h(-1),
00064 maxGrey(1),
00065 comments("")
00066 {
00067 ASSERT(owned_strm.get() != 0);
00068 strm = owned_strm.get();
00069 }
00070
00071 Rep(std::istream& strm_) :
00072 fname("(anonymous stream)"),
00073 owned_strm(),
00074 strm(&strm_),
00075 mode(-1),
00076 w(-1),
00077 h(-1),
00078 maxGrey(1),
00079 comments("")
00080 {}
00081
00082 void init();
00083
00084
00085 void readPixels8(byte* space, int nvals);
00086
00087
00088 void readPixels16(uint16* space, int nvals);
00089
00090
00091
00092
00093 Image<byte> parseBW();
00094
00095
00096
00097 Image<byte> parseGrayU8();
00098
00099
00100
00101 Image<uint16> parseGrayU16();
00102
00103
00104
00105 Image<PixRGB<byte> > parseRgbU8();
00106
00107
00108
00109 Image<PixRGB<uint16> > parseRgbU16();
00110
00111 std::string fname;
00112 rutz::shared_ptr<std::istream> owned_strm;
00113 std::istream* strm;
00114 int mode;
00115 int w, h;
00116 int maxGrey;
00117 std::string comments;
00118 };
00119
00120
00121 void PnmParser::Rep::init()
00122 {
00123 int c = this->strm->get();
00124 if (c != 'P')
00125 LFATAL("Missing magic number in pnm file '%s'"
00126 "(got '%c' [%d], expected '%c' [%d]).",
00127 fname.c_str(), c, c, 'P', 'P');
00128
00129 *(this->strm) >> this->mode;
00130
00131 *(this->strm) >> std::ws;
00132
00133
00134
00135 std::string temp;
00136
00137 while ( this->strm->peek() == '#' )
00138 {
00139
00140 std::getline( *(this->strm), temp, '\n');
00141 this->comments += temp;
00142
00143
00144
00145 }
00146
00147 *(this->strm) >> this->w >> this->h;
00148
00149 if (this->mode != 1 && this->mode != 4)
00150 {
00151 *(this->strm) >> this->maxGrey;
00152 }
00153
00154
00155 c = this->strm->get();
00156 if ( !isspace(c) )
00157 LFATAL("Missing whitespace after maxGrey in pbm file '%s'.",
00158 fname.c_str());
00159 }
00160
00161
00162 void PnmParser::Rep::readPixels8(byte* p, int nvals)
00163 {
00164 ASSERT(this->mode == 2 || this->mode == 3 || this->mode == 5 || this->mode == 6);
00165
00166 ASSERT(this->maxGrey > 0);
00167 ASSERT(this->maxGrey <= 255);
00168
00169 const double scale = 255.0/double(this->maxGrey);
00170
00171 if (this->mode == 2 || this->mode == 3)
00172 {
00173
00174 int position = 0;
00175 int val = 0;
00176
00177 while (this->strm->peek() != EOF && position < nvals)
00178 {
00179 *(this->strm) >> val;
00180 p[position++] = static_cast<byte>(val * scale);
00181 }
00182 }
00183 else
00184 {
00185
00186 this->strm->read(reinterpret_cast<char*>(p), nvals);
00187
00188 if (this->maxGrey != 255)
00189 for (int i = 0; i < nvals; ++i)
00190 {
00191 if (p[i] > this->maxGrey)
00192 {
00193 LERROR("%s: value %d was %d but maxgrey "
00194 "is claimed to be %d",
00195 this->fname.c_str(), i, p[i], this->maxGrey);
00196 p[i] = this->maxGrey;
00197 }
00198 p[i] = byte(p[i] * scale);
00199 }
00200 }
00201 }
00202
00203
00204 void PnmParser::Rep::readPixels16(uint16* p, int nvals)
00205 {
00206 ASSERT(this->mode == 2 || this->mode == 3 || this->mode == 5 || this->mode == 6);
00207
00208 ASSERT(this->maxGrey >= 256);
00209 ASSERT(this->maxGrey <= 65535);
00210
00211 const double scale = 65535.0/double(this->maxGrey);
00212
00213 if (this->mode == 2 || this->mode == 3)
00214 {
00215
00216 int position = 0;
00217 int val = 0;
00218
00219 while (this->strm->peek() != EOF && position < nvals)
00220 {
00221 *(this->strm) >> val;
00222 p[position++] = static_cast<uint16>(val * scale);
00223 }
00224 }
00225 else
00226 {
00227
00228 this->strm->read(reinterpret_cast<char*>(p), nvals * 2);
00229
00230 union { byte b[2]; uint16 u16; } u;
00231 u.b[0] = 0; u.b[1] = 1;
00232
00233 if (u.u16 != 1)
00234 {
00235 for (int i = 0; i < nvals; ++i)
00236 p[i] = ((p[i] & 0xff00) >> 8) | ((p[i] & 0x00ff) << 8);
00237 }
00238
00239 if (this->maxGrey != 65535)
00240 for (int i = 0; i < nvals; ++i)
00241 {
00242 if (p[i] > this->maxGrey)
00243 {
00244 LERROR("%s: value %d was %d but maxgrey "
00245 "is claimed to be %d",
00246 this->fname.c_str(), i, p[i], this->maxGrey);
00247 p[i] = this->maxGrey;
00248 }
00249 p[i] = uint16(p[i] * scale);
00250 }
00251 }
00252 }
00253
00254
00255 Image<byte> PnmParser::Rep::parseBW()
00256 {
00257 ASSERT(this->mode == 1 || this->mode == 4);
00258
00259 Image<byte> img(this->w, this->h, NO_INIT);
00260
00261 if (this->mode == 1)
00262 {
00263 Image<byte>::iterator itr = img.beginw(), stop = img.endw();
00264
00265 while (itr != stop)
00266 {
00267 const int c = this->strm->get();
00268 if (c == EOF)
00269 LFATAL("while parsing %s: premature EOF before pixel #%d",
00270 this->fname.c_str(), int(stop - itr));
00271
00272 if (isspace(c))
00273 continue;
00274
00275 if (c == '0')
00276 *itr++ = 255;
00277 else if (c == '1')
00278 *itr++ = 0;
00279 else
00280 LFATAL("while parsing %s: "
00281 "invalid pixel value '%c' at pixel #%d",
00282 this->fname.c_str(), c, int(stop - itr));
00283 }
00284 }
00285 else if (this->mode == 4)
00286 {
00287 Image<byte>::iterator itr = img.beginw(), stop = img.endw();
00288
00289 int c = 0;
00290 int pos = 7;
00291
00292 while (itr != stop)
00293 {
00294 if (pos == 7)
00295 {
00296 c = this->strm->get();
00297 if (c == EOF)
00298 LFATAL("while parsing %s: premature EOF before pixel #%d",
00299 this->fname.c_str(), int(stop - itr));
00300 }
00301
00302 if (c & (1 << pos))
00303 *itr++ = 0;
00304 else
00305 *itr++ = 255;
00306
00307 if (pos == 0) pos = 7;
00308 else --pos;
00309 }
00310 }
00311
00312 return img;
00313 }
00314
00315
00316 Image<byte> PnmParser::Rep::parseGrayU8()
00317 {
00318 ASSERT(this->mode == 2 || this->mode == 5);
00319
00320 Image<byte> img(this->w, this->h, NO_INIT);
00321 this->readPixels8(img.getArrayPtr(), img.getSize());
00322 return img;
00323 }
00324
00325
00326 Image<uint16> PnmParser::Rep::parseGrayU16()
00327 {
00328 ASSERT(this->mode == 2 || this->mode == 5);
00329
00330 Image<uint16> img(this->w, this->h, NO_INIT);
00331 this->readPixels16(img.getArrayPtr(), img.getSize());
00332 return img;
00333 }
00334
00335
00336 Image<PixRGB<byte> > PnmParser::Rep::parseRgbU8()
00337 {
00338 ASSERT(this->mode == 3 || this->mode == 6);
00339
00340 Image<PixRGB<byte> > img(this->w, this->h, NO_INIT);
00341 this->readPixels8(reinterpret_cast<byte*>(img.getArrayPtr()), img.getSize()*3);
00342 return img;
00343 }
00344
00345
00346 Image<PixRGB<uint16> > PnmParser::Rep::parseRgbU16()
00347 {
00348 ASSERT(this->mode == 3 || this->mode == 6);
00349
00350 Image<PixRGB<uint16> > img(this->w, this->h, NO_INIT);
00351 this->readPixels16(reinterpret_cast<uint16*>(img.getArrayPtr()), img.getSize()*3);
00352 return img;
00353 }
00354
00355
00356 PnmParser::PnmParser(const char* fname) :
00357 rep(new Rep(fname))
00358 {
00359 rep->init();
00360 }
00361
00362
00363 PnmParser::PnmParser(std::istream& strm) :
00364 rep(new Rep(strm))
00365 {
00366 rep->init();
00367 }
00368
00369
00370 PnmParser::~PnmParser()
00371 {
00372 delete rep;
00373 }
00374
00375
00376 GenericFrameSpec PnmParser::getFrameSpec() const
00377 {
00378 GenericFrameSpec result;
00379
00380 switch (rep->mode)
00381 {
00382 case 1: case 4:
00383 result.nativeType = GenericFrame::GRAY_U8;
00384 break;
00385
00386 case 2: case 5:
00387 result.nativeType =
00388 rep->maxGrey <= 255
00389 ? GenericFrame::GRAY_U8
00390 : GenericFrame::GRAY_F32;
00391 break;
00392
00393 case 3: case 6:
00394 result.nativeType =
00395 rep->maxGrey <= 255
00396 ? GenericFrame::RGB_U8
00397 : GenericFrame::RGB_F32;
00398 break;
00399
00400 default:
00401 LFATAL("invalid PNM mode '%d'", rep->mode);
00402 }
00403
00404 result.videoFormat = VIDFMT_AUTO;
00405 result.videoByteSwap = false;
00406 result.dims = Dims(rep->w, rep->h);
00407 result.floatFlags = 0;
00408
00409 return result;
00410 }
00411
00412
00413 std::string PnmParser::getComments() const
00414 { return rep->comments; }
00415
00416
00417 uint PnmParser::getTagCount() const
00418 { return 0; }
00419
00420
00421 bool PnmParser::getTag(uint tag, std::string &name, std::string &value) const
00422 { return false; }
00423
00424
00425 GenericFrame PnmParser::getFrame()
00426 {
00427 switch (rep->mode)
00428 {
00429 case 1: case 4:
00430 return GenericFrame(rep->parseBW());
00431 break;
00432
00433 case 2: case 5:
00434 if (rep->maxGrey <= 255)
00435 return GenericFrame(rep->parseGrayU8());
00436 else
00437 {
00438 const Image<uint16> gray16(rep->parseGrayU16());
00439 Image<float> ret(gray16.getDims(), NO_INIT);
00440 Image<uint16>::const_iterator sptr = gray16.begin();
00441 Image<float>::iterator fptr = ret.beginw();
00442 Image<float>::iterator const stop = ret.endw();
00443
00444
00445
00446 while (fptr != stop)
00447 *fptr++ = *sptr++ / 256.0f;
00448 return GenericFrame(ret, 0);
00449 }
00450 break;
00451
00452 case 3: case 6:
00453 if (rep->maxGrey <= 255)
00454 return GenericFrame(rep->parseRgbU8());
00455 else
00456 {
00457 const Image<PixRGB<uint16> > rgb16(rep->parseRgbU16());
00458 Image<PixRGB<float> > ret(rgb16.getDims(), NO_INIT);
00459 Image<PixRGB<uint16> >::const_iterator sptr = rgb16.begin();
00460 Image<PixRGB<float> >::iterator fptr = ret.beginw();
00461 Image<PixRGB<float> >::iterator const stop = ret.endw();
00462
00463
00464
00465 while (fptr != stop)
00466 *fptr++ = PixRGB<float>(*sptr++) / 256.0f;
00467 return GenericFrame(ret, 0);
00468 }
00469 break;
00470 }
00471
00472 LFATAL("invalid PNM mode '%d'", rep->mode);
00473 return GenericFrame();
00474 }
00475
00476
00477
00478
00479
00480