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/Raster.H"
00039
00040 #include "Image/ColorOps.H"
00041 #include "Image/Image.H"
00042 #include "Image/MathOps.H"
00043 #include "Image/Pixels.H"
00044 #include "Raster/CcodeWriter.H"
00045 #include "Raster/DpxParser.H"
00046 #include "Raster/GenericFrame.H"
00047 #include "Raster/JpegParser.H"
00048 #include "Raster/PfmParser.H"
00049 #include "Raster/PfmWriter.H"
00050 #include "Raster/PfzParser.H"
00051 #include "Raster/PfzWriter.H"
00052 #include "Raster/PlaintextWriter.H"
00053 #include "Raster/PngParser.H"
00054 #include "Raster/PngWriter.H"
00055 #include "Raster/PnmParser.H"
00056 #include "Raster/PnmWriter.H"
00057 #include "Raster/QuartzQuickTimeParser.H"
00058 #include "Raster/RawWriter.H"
00059 #include "Raster/YuvParser.H"
00060 #include "Raster/YuvWriter.H"
00061 #include "Util/Assert.H"
00062 #include "Util/FileUtil.H"
00063 #include "Util/log.H"
00064 #include "Video/VideoFrame.H"
00065 #include "rutz/shared_ptr.h"
00066 #include "rutz/trace.h"
00067
00068 #include <cerrno>
00069 #include <cstring>
00070 #include <fcntl.h>
00071 #include <list>
00072 #include <sys/stat.h>
00073 #include <sys/types.h>
00074
00075
00076
00077
00078 namespace
00079 {
00080 const int MODE_R = (1 << 0);
00081 const int MODE_W = (1 << 1);
00082
00083
00084
00085 struct RasFileExtension
00086 {
00087 const char* extension;
00088 RasterFileFormat format;
00089 int modes;
00090 };
00091
00092
00093
00094 const RasFileExtension allExtensions[] =
00095 {
00096 { ".pnm", RASFMT_PNM, MODE_R | MODE_W },
00097 { ".ppm", RASFMT_PNM, MODE_R | MODE_W },
00098 { ".pgm", RASFMT_PNM, MODE_R | MODE_W },
00099 { ".pbm", RASFMT_PNM, MODE_R | MODE_W },
00100
00101 { ".pnm.gz", RASFMT_PNM, MODE_R },
00102 { ".ppm.gz", RASFMT_PNM, MODE_R },
00103 { ".pgm.gz", RASFMT_PNM, MODE_R },
00104 { ".pbm.gz", RASFMT_PNM, MODE_R },
00105
00106 { ".pnm.bz2", RASFMT_PNM, MODE_R },
00107 { ".ppm.bz2", RASFMT_PNM, MODE_R },
00108 { ".pgm.bz2", RASFMT_PNM, MODE_R },
00109 { ".pbm.bz2", RASFMT_PNM, MODE_R },
00110
00111 { ".pfm", RASFMT_PFM, MODE_R | MODE_W },
00112 { ".pfm.gz", RASFMT_PFM, MODE_R | MODE_W },
00113 { ".pfm.bz2", RASFMT_PFM, MODE_R | MODE_W },
00114
00115 { ".png", RASFMT_PNG, MODE_R | MODE_W },
00116 { ".pfz", RASFMT_PFZ, MODE_R | MODE_W },
00117 { ".jpg", RASFMT_JPEG, MODE_R },
00118 { ".jpeg", RASFMT_JPEG, MODE_R },
00119
00120 { ".txt", RASFMT_TXT, MODE_W },
00121 { ".C", RASFMT_CCODE, MODE_W },
00122 { ".dpx", RASFMT_DPX, MODE_R },
00123
00124 { ".rgb555", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00125 { ".rgb565", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00126 { ".rgb24", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00127 { ".rgb32", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00128 { ".yuv24", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00129 { ".yuyv", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00130 { ".uyvy", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00131 { ".yuv444", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00132 { ".yuv422", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00133 { ".yuv411", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00134 { ".yuv420", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00135 { ".yuv410", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00136 { ".yuv444p", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00137 { ".yuv422p", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00138 { ".yuv411p", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00139 { ".yuv420p", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00140 { ".yuv410p", RASFMT_RAW_VIDEO, MODE_R | MODE_W },
00141
00142 { ".bayer", RASFMT_RAW_IMAGE, MODE_R | MODE_W },
00143
00144 { ".rgb555.gz", RASFMT_RAW_VIDEO, MODE_R },
00145 { ".rgb565.gz", RASFMT_RAW_VIDEO, MODE_R },
00146 { ".rgb24.gz", RASFMT_RAW_VIDEO, MODE_R },
00147 { ".rgb32.gz", RASFMT_RAW_VIDEO, MODE_R },
00148 { ".yuv24.gz", RASFMT_RAW_VIDEO, MODE_R },
00149 { ".yuyv.gz", RASFMT_RAW_VIDEO, MODE_R },
00150 { ".uyvy.gz", RASFMT_RAW_VIDEO, MODE_R },
00151 { ".yuv444.gz", RASFMT_RAW_VIDEO, MODE_R },
00152 { ".yuv422.gz", RASFMT_RAW_VIDEO, MODE_R },
00153 { ".yuv411.gz", RASFMT_RAW_VIDEO, MODE_R },
00154 { ".yuv420.gz", RASFMT_RAW_VIDEO, MODE_R },
00155 { ".yuv410.gz", RASFMT_RAW_VIDEO, MODE_R },
00156 { ".yuv444p.gz", RASFMT_RAW_VIDEO, MODE_R },
00157 { ".yuv422p.gz", RASFMT_RAW_VIDEO, MODE_R },
00158 { ".yuv411p.gz", RASFMT_RAW_VIDEO, MODE_R },
00159 { ".yuv420p.gz", RASFMT_RAW_VIDEO, MODE_R },
00160 { ".yuv410p.gz", RASFMT_RAW_VIDEO, MODE_R },
00161
00162 { ".rgb555.bz2", RASFMT_RAW_VIDEO, MODE_R },
00163 { ".rgb565.bz2", RASFMT_RAW_VIDEO, MODE_R },
00164 { ".rgb24.bz2", RASFMT_RAW_VIDEO, MODE_R },
00165 { ".rgb32.bz2", RASFMT_RAW_VIDEO, MODE_R },
00166 { ".yuv24.bz2", RASFMT_RAW_VIDEO, MODE_R },
00167 { ".yuyv.bz2", RASFMT_RAW_VIDEO, MODE_R },
00168 { ".uyvy.bz2", RASFMT_RAW_VIDEO, MODE_R },
00169 { ".yuv444.bz2", RASFMT_RAW_VIDEO, MODE_R },
00170 { ".yuv422.bz2", RASFMT_RAW_VIDEO, MODE_R },
00171 { ".yuv411.bz2", RASFMT_RAW_VIDEO, MODE_R },
00172 { ".yuv420.bz2", RASFMT_RAW_VIDEO, MODE_R },
00173 { ".yuv410.bz2", RASFMT_RAW_VIDEO, MODE_R },
00174 { ".yuv444p.bz2", RASFMT_RAW_VIDEO, MODE_R },
00175 { ".yuv422p.bz2", RASFMT_RAW_VIDEO, MODE_R },
00176 { ".yuv411p.bz2", RASFMT_RAW_VIDEO, MODE_R },
00177 { ".yuv420p.bz2", RASFMT_RAW_VIDEO, MODE_R },
00178 { ".yuv410p.bz2", RASFMT_RAW_VIDEO, MODE_R },
00179
00180
00181 { 0, RASFMT_AUTO, 0 }
00182 };
00183
00184
00185 struct RasFileDefaultExtension
00186 {
00187 const char* extension;
00188 RasterFileFormat format;
00189 };
00190
00191
00192
00193 const RasFileDefaultExtension defaultExtensions[] =
00194 {
00195 { ".pnm", RASFMT_PNM },
00196 { ".png", RASFMT_PNG },
00197 { ".pfm", RASFMT_PFM },
00198 { ".pfz", RASFMT_PFZ },
00199 { ".jpg", RASFMT_JPEG },
00200 { ".txt", RASFMT_TXT },
00201 { ".C", RASFMT_CCODE },
00202 { ".dpx", RASFMT_DPX },
00203
00204
00205
00206
00207
00208 { 0, RASFMT_AUTO }
00209 };
00210
00211
00212 bool hasMatchingExtension(const std::string& fname,
00213 const RasterFileFormat ftype,
00214 const int mode)
00215 {
00216 for (const RasFileExtension* p = &allExtensions[0];
00217 p->extension != 0; ++p)
00218 {
00219 if (p->format == ftype
00220 && hasExtension(fname, p->extension)
00221 && ((p->modes & mode) != 0))
00222 return true;
00223 }
00224
00225 return false;
00226 }
00227
00228
00229 const char* defaultExtensionFor(const RasterFileFormat ftype)
00230 {
00231 for (const RasFileDefaultExtension* p = &defaultExtensions[0];
00232 p->extension != 0; ++p)
00233 {
00234 if (p->format == ftype)
00235 return p->extension;
00236 }
00237
00238
00239 return "";
00240 }
00241
00242
00243
00244
00245 std::string getExtensionListString(const int mode)
00246 {
00247 std::list<std::string> xlist;
00248 for (const RasFileExtension* p = &allExtensions[0];
00249 p->extension != 0; ++p)
00250 if ((p->modes & mode) != 0)
00251 xlist.push_back(p->extension);
00252
00253 xlist.sort();
00254
00255 std::string xstr;
00256 bool first = true;
00257
00258 for (std::list<std::string>::iterator
00259 itr = xlist.begin(), stop = xlist.end();
00260 itr != stop; ++itr)
00261 {
00262 if (!first)
00263 xstr += ", ";
00264 xstr += '\'';
00265 xstr += *itr;
00266 xstr += '\'';
00267 first = false;
00268 }
00269
00270 return xstr;
00271 }
00272
00273
00274 rutz::shared_ptr<RasterParser> makeParser(RasterFileFormat ftype,
00275 const char* fname)
00276 {
00277 GVX_TRACE(__PRETTY_FUNCTION__);
00278
00279 switch (ftype)
00280 {
00281 case RASFMT_PNM: return rutz::shared_ptr<RasterParser>(new PnmParser(fname));
00282 #if defined(INVT_HAVE_LIBPNG)
00283 case RASFMT_PNG: return rutz::shared_ptr<RasterParser>(new PngParser(fname));
00284 #elif defined(HAVE_QUICKTIME_QUICKTIME_H)
00285 case RASFMT_PNG: return rutz::shared_ptr<RasterParser>(new QuartzQuickTimeParser(fname));
00286 #endif
00287 case RASFMT_PFM: return rutz::shared_ptr<RasterParser>(new PfmParser(fname));
00288 case RASFMT_PFZ: return rutz::shared_ptr<RasterParser>(new PfzParser(fname));
00289 case RASFMT_RAW_VIDEO: return rutz::shared_ptr<RasterParser>(new YuvParser(fname));
00290 #if defined(INVT_HAVE_LIBJPEG)
00291 case RASFMT_JPEG: return rutz::shared_ptr<RasterParser>(new JpegParser(fname));
00292 #elif defined(HAVE_QUICKTIME_QUICKTIME_H)
00293 case RASFMT_JPEG: return rutz::shared_ptr<RasterParser>(new QuartzQuickTimeParser(fname));
00294 #endif
00295 case RASFMT_DPX: return rutz::shared_ptr<RasterParser>(new DpxParser(fname));
00296 default:
00297 {
00298 LFATAL("Unsupported file type: %s (%d) for reading filename '%s'",
00299 convertToString(ftype).c_str(), int(ftype), fname);
00300 }
00301 }
00302 return rutz::shared_ptr<RasterParser>();
00303 }
00304
00305
00306 rutz::shared_ptr<RasterWriter> makeWriter(RasterFileFormat ftype,
00307 const char* fname)
00308 {
00309 GVX_TRACE(__PRETTY_FUNCTION__);
00310
00311 switch (ftype)
00312 {
00313 case RASFMT_PNM: return rutz::make_shared(new PnmWriter(hasExtension(fname, ".pbm"), 128));
00314 #ifdef INVT_HAVE_LIBPNG
00315 case RASFMT_PNG: return rutz::make_shared(new PngWriter);
00316 #endif
00317 case RASFMT_PFM: return rutz::make_shared(new PfmWriter);
00318 case RASFMT_PFZ: return rutz::make_shared(new PfzWriter);
00319 case RASFMT_RAW_VIDEO: return rutz::make_shared(new YuvWriter);
00320 case RASFMT_RAW_IMAGE: return rutz::make_shared(new RawWriter);
00321 case RASFMT_TXT: return rutz::make_shared(new PlaintextWriter);
00322 case RASFMT_CCODE: return rutz::make_shared(new CcodeWriter);
00323 default:
00324 {
00325 LFATAL("Unsupported file type: %s (%d) for writing filename '%s'",
00326 convertToString(ftype).c_str(), int(ftype), fname);
00327 }
00328 }
00329 return rutz::shared_ptr<RasterWriter>();
00330 }
00331
00332
00333 RasterFileFormat addFileExtension(std::string& fname,
00334 const RasterFileFormat ftype,
00335 const int mode,
00336 const bool fatal)
00337 {
00338 GVX_TRACE(__PRETTY_FUNCTION__);
00339
00340
00341
00342
00343 if (ftype == RASFMT_AUTO)
00344 {
00345 for (const RasFileExtension* p = &allExtensions[0];
00346 p->extension != 0; ++p)
00347 {
00348 if (((p->modes & mode) != 0)
00349 && hasExtension(fname, p->extension))
00350 return p->format;
00351 }
00352
00353 const std::string xlist = getExtensionListString(mode);
00354
00355 if (fatal)
00356 LFATAL("couldn't determine RasterFileFormat from filename '%s'"
00357 " (known raster file extensions: [%s])",
00358 fname.c_str(), xlist.c_str());
00359 else
00360 return RASFMT_AUTO;
00361 }
00362
00363 if (!hasMatchingExtension(fname, ftype, mode))
00364 fname += defaultExtensionFor(ftype);
00365
00366 return ftype;
00367 }
00368
00369 }
00370
00371
00372
00373
00374
00375
00376
00377
00378 bool Raster::fileExists(std::string fname,
00379 const RasterFileFormat ftype,
00380 const bool chkFormat)
00381 {
00382 GVX_TRACE(__PRETTY_FUNCTION__);
00383 RasterFileFormat ff = addFileExtension(fname, ftype, MODE_R, false);
00384 if (chkFormat && ff == RASFMT_AUTO)
00385 return false;
00386 const int fd = open(fname.c_str(), O_RDONLY);
00387 if (fd == -1)
00388 {
00389 if (errno != ENOENT)
00390 PLERROR("Cannot open '%s'", fname.c_str());
00391 return false;
00392 }
00393 close(fd);
00394 return true;
00395 }
00396
00397
00398 std::string Raster::getImageComments(std::string fname,
00399 const RasterFileFormat ftype)
00400 {
00401 GVX_TRACE(__PRETTY_FUNCTION__);
00402 RasterFileFormat newftype = addFileExtension(fname, ftype, MODE_R, true);
00403
00404 rutz::shared_ptr<RasterParser> pp(makeParser(newftype, fname.c_str()));
00405 return pp->getComments();
00406 }
00407
00408
00409 Dims Raster::getImageDims(std::string fname,
00410 const RasterFileFormat ftype)
00411 {
00412 GVX_TRACE(__PRETTY_FUNCTION__);
00413 GenericFrameSpec spec = Raster::getFrameSpec(fname, ftype);
00414 return spec.dims;
00415 }
00416
00417
00418 GenericFrameSpec Raster::getFrameSpec(std::string fname,
00419 const RasterFileFormat ftype)
00420 {
00421 GVX_TRACE(__PRETTY_FUNCTION__);
00422 RasterFileFormat newftype = addFileExtension(fname, ftype, MODE_R, true);
00423
00424 rutz::shared_ptr<RasterParser> pp(makeParser(newftype, fname.c_str()));
00425 return pp->getFrameSpec();
00426 }
00427
00428
00429 GenericFrame Raster::ReadFrame(std::string fname,
00430 RasterFileFormat ftype)
00431 {
00432 GVX_TRACE(__PRETTY_FUNCTION__);
00433 ftype = addFileExtension(fname, ftype, MODE_R, true);
00434 LDEBUG("reading raster file: %s", fname.c_str());
00435
00436 rutz::shared_ptr<RasterParser> pp(makeParser(ftype, fname.c_str()));
00437 return pp->getFrame();
00438 }
00439
00440
00441 Image<PixRGB<byte> > Raster::ReadRGB(std::string fname,
00442 const RasterFileFormat ftype)
00443 {
00444 GVX_TRACE(__PRETTY_FUNCTION__);
00445 return Raster::ReadFrame(fname, ftype).asRgb();
00446 }
00447
00448
00449 Image<byte> Raster::ReadGray(std::string fname,
00450 const RasterFileFormat ftype)
00451 {
00452 GVX_TRACE(__PRETTY_FUNCTION__);
00453 return Raster::ReadFrame(fname, ftype).asGray();
00454 }
00455
00456
00457 Image<byte> Raster::ReadGrayNTSC(std::string fname,
00458 const RasterFileFormat ftype)
00459 {
00460 GVX_TRACE(__PRETTY_FUNCTION__);
00461 return Raster::ReadFrame(fname, ftype).asGrayNTSC();
00462 }
00463
00464
00465
00466 Image<float> Raster::ReadFloat(std::string fname,
00467 const RasterFileFormat ftype)
00468 {
00469 GVX_TRACE(__PRETTY_FUNCTION__);
00470 return Raster::ReadFrame(fname, ftype).asFloat();
00471 }
00472
00473
00474 VideoFrame Raster::ReadVideo(std::string fname,
00475 const RasterFileFormat ftype)
00476 {
00477 GVX_TRACE(__PRETTY_FUNCTION__);
00478 return Raster::ReadFrame(fname, ftype).asVideo();
00479 }
00480
00481
00482 std::string Raster::WriteFrame(const GenericFrame& image,
00483 std::string fname,
00484 RasterFileFormat ftype)
00485 {
00486 GVX_TRACE(__PRETTY_FUNCTION__);
00487
00488 if (!image.initialized())
00489 LFATAL("image was empty when trying to write to %s", fname.c_str());
00490
00491 ftype = addFileExtension(fname, ftype, MODE_W, true);
00492 LDEBUG("writing raster file: %s", fname.c_str());
00493
00494 rutz::shared_ptr<RasterWriter> writer = makeWriter(ftype, fname.c_str());
00495 return writer->writeFrame(image, fname);
00496 }
00497
00498
00499 std::string Raster::WriteRGB(const Image< PixRGB<byte> >& image,
00500 std::string fname,
00501 const RasterFileFormat ftype)
00502 {
00503 GVX_TRACE(__PRETTY_FUNCTION__);
00504 return Raster::WriteFrame(GenericFrame(image), fname, ftype);
00505 }
00506
00507
00508 std::string Raster::WriteGray(const Image<byte>& image,
00509 std::string fname,
00510 const RasterFileFormat ftype)
00511 {
00512 GVX_TRACE(__PRETTY_FUNCTION__);
00513 return Raster::WriteFrame(GenericFrame(image), fname, ftype);
00514 }
00515
00516
00517 std::string Raster::WriteFloat(const Image<float>& image,
00518 const int flags,
00519 std::string fname,
00520 const RasterFileFormat ftype)
00521 {
00522 GVX_TRACE(__PRETTY_FUNCTION__);
00523 return Raster::WriteFrame(GenericFrame(image, flags), fname, ftype);
00524 }
00525
00526 namespace
00527 {
00528 bool USING_XV = true;
00529 }
00530
00531
00532 void Raster::NoXV()
00533 {
00534 GVX_TRACE(__PRETTY_FUNCTION__);
00535 USING_XV = false;
00536 }
00537
00538
00539 void Raster::Display(const char* file)
00540 {
00541 GVX_TRACE(__PRETTY_FUNCTION__);
00542 if (USING_XV)
00543 {
00544 std::string command("xv \"");
00545 command += file;
00546 command += "\" &";
00547 int ret = system(command.c_str());
00548 if (ret) LERROR("Display command returned: %d", ret);
00549 }
00550 }
00551
00552
00553 void Raster::waitForKey()
00554 {
00555 GVX_TRACE(__PRETTY_FUNCTION__);
00556 char tmp[100];
00557 printf("<<<<< Press <Return> to continue >>>>>\n");
00558
00559
00560 char* ret = fgets(tmp, 100, stdin);
00561 if (ret);
00562 }
00563
00564
00565 void Raster::VisuRGB(const Image< PixRGB<byte> >& image,
00566 std::string fname,
00567 const RasterFileFormat ftype)
00568 {
00569 GVX_TRACE(__PRETTY_FUNCTION__);
00570 fname = Raster::WriteRGB(image, fname, ftype);
00571
00572 byte mi, ma; getMinMaxC(image, mi, ma);
00573 LINFO("%s [%d..%d]", fname.c_str(), int(mi), int(ma));
00574
00575 Raster::Display(fname.c_str());
00576 }
00577
00578
00579 void Raster::VisuGray(const Image<byte>& image,
00580 std::string fname,
00581 RasterFileFormat ftype)
00582 {
00583 GVX_TRACE(__PRETTY_FUNCTION__);
00584 fname = Raster::WriteGray(image, fname, ftype);
00585
00586 byte mi, ma; getMinMax(image, mi, ma);
00587 LINFO("%s [%d..%d]", fname.c_str(), int(mi), int(ma));
00588
00589 Raster::Display(fname.c_str());
00590 }
00591
00592
00593 void Raster::VisuFloat(const Image<float>& image,
00594 const int flags,
00595 std::string fname,
00596 RasterFileFormat ftype)
00597 {
00598 GVX_TRACE(__PRETTY_FUNCTION__);
00599 fname = Raster::WriteFloat(image, flags, fname, ftype);
00600
00601 float mi, ma; getMinMax(image, mi, ma);
00602 if (flags & FLOAT_NORM_0_255)
00603 LINFO("%s [%f..%f] -- Normalized", fname.c_str(), mi, ma);
00604 else
00605 LINFO("%s [%f..%f]", fname.c_str(), mi, ma);
00606
00607 Raster::Display(fname.c_str());
00608 }
00609
00610
00611
00612
00613
00614