TuttleOFX  1
main.cpp
Go to the documentation of this file.
00001 #include <sam/common/utility.hpp>
00002 #include <sam/common/options.hpp>
00003 
00004 #include <boost/filesystem/operations.hpp>
00005 #include <boost/filesystem/exception.hpp>
00006 #include <boost/exception/diagnostic_information.hpp>
00007 #include <boost/foreach.hpp>
00008 #include <boost/algorithm/string.hpp>
00009 #include <boost/algorithm/string/split.hpp>
00010 #include <boost/program_options.hpp>
00011 #include <boost/shared_ptr.hpp>
00012 
00013 #include <magick/MagickCore.h>
00014 
00015 #include <detector.hpp>
00016 
00017 #include <algorithm>
00018 #include <iterator>
00019 
00020 #define FIRST_COLUMN_WIDTH 23
00021 
00022 namespace bpo = boost::program_options;
00023 namespace bfs = boost::filesystem;
00024 namespace bal = boost::algorithm;
00025 
00026 
00027 int     firstImage      = 0;
00028 int     lastImage       = 0;
00029 
00030 namespace sam
00031 {
00032         bool wasSthgDumped = false;
00033 }
00034 
00035 
00036 void printImageProperties( std::string path )
00037 {
00038         try
00039         {
00040                 Image         *image;
00041                 ImageInfo     *image_info;
00042                 
00043                 // Read a file into image object
00044                 image_info = AcquireImageInfo();
00045                 GetImageInfo( image_info );
00046 
00047                 strcpy( image_info -> filename, path.c_str() );
00048 
00049                 ExceptionInfo* exceptionsInfo = AcquireExceptionInfo();
00050                 GetExceptionInfo( exceptionsInfo );
00051                 
00052                 image = ReadImage( image_info, exceptionsInfo );
00053                 
00054                 std::string imageType;
00055                 switch( image->type )
00056                 {
00057                         case UndefinedType             : imageType = "Undefined type of image"; break;
00058                         case BilevelType               : imageType = "Bilevel image"; break;
00059                         case GrayscaleType             : imageType = "Grayscale image"; break;
00060                         case GrayscaleMatteType        : imageType = "Grayscale image with opacity"; break;
00061                         case PaletteType               : imageType = "Indexed color image"; break;
00062                         case PaletteMatteType          : imageType = "Indexed color image with opacity"; break;
00063                         case TrueColorType             : imageType = "Truecolor image"; break;
00064                         case TrueColorMatteType        : imageType = "Truecolor image with opacity"; break;
00065                         case ColorSeparationType       : imageType = "Cyan/Yellow/Magenta/Black (CYMK) image"; break;
00066                         case ColorSeparationMatteType  : imageType = "Cyan/Yellow/Magenta/Black (CYMK) image with opacity"; break;
00067                         case OptimizeType              : imageType = "Optimize image"; break;
00068                         case 11                        : imageType = "Indexed bilevel image with opacity"; break; // PaletteBilevelMatteType
00069                 }
00070 
00071                 std::string resolutionType;
00072                 switch( image->units )
00073                 {
00074                         case UndefinedResolution            : resolutionType = " [unknown units]"; break;
00075                         case PixelsPerInchResolution        : resolutionType = " [dpi]"; break;
00076                         case PixelsPerCentimeterResolution  : resolutionType = " [pixels/cm]"; break;
00077                 }
00078 
00079                 std::string colorSpaceType;
00080                 switch( image->colorspace )
00081                 {
00082                         case UndefinedColorspace      : colorSpaceType = "unknown color space"; break;
00083                         case RGBColorspace            : colorSpaceType = "RGB"; break;
00084                         case GRAYColorspace           : colorSpaceType = "Gray"; break;
00085                         case TransparentColorspace    : colorSpaceType = "Transparent"; break;
00086                         case OHTAColorspace           : colorSpaceType = "OHTA"; break;
00087                         case XYZColorspace            : colorSpaceType = "XYZ"; break;
00088                         case YCbCrColorspace          : colorSpaceType = "Y Cb Cr"; break;
00089                         case YCCColorspace            : colorSpaceType = "YCC"; break;
00090                         case YIQColorspace            : colorSpaceType = "YIQ"; break;
00091                         case YPbPrColorspace          : colorSpaceType = "Y Pb Pr"; break;
00092                         case YUVColorspace            : colorSpaceType = "YUV"; break;
00093                         case CMYKColorspace           : colorSpaceType = "CMYK"; break;
00094                         case sRGBColorspace           : colorSpaceType = "sRGB"; break;
00095                         case LabColorspace            : colorSpaceType = "Lab"; break;
00096                         case 14                       : colorSpaceType = "HSB"; break; // HSBColorspace
00097                         case HSLColorspace            : colorSpaceType = "HSL"; break;
00098                         case HWBColorspace            : colorSpaceType = "HWB"; break;
00099                         case Rec601LumaColorspace     : colorSpaceType = "Rec601 Luma"; break;
00100                         case 18                       : colorSpaceType = "Rec601 Y Cb Cr"; break; // Rec601YCbCrColorspace
00101                         case Rec709LumaColorspace     : colorSpaceType = "Rec709 Luma"; break;
00102                         case 20                       : colorSpaceType = "Rec709 Y Cb Cr"; break; //  Rec709YCbCrColorspace
00103                         case LogColorspace            : colorSpaceType = "Log"; break;
00104                         case 22                       : colorSpaceType = "CMY"; break; // CMYColorspace
00105 #if MagickLibVersion > 0x677
00106                         case LuvColorspace            : colorSpaceType = "Luv"; break;
00107                         case HCLColorspace            : colorSpaceType = "HCL"; break;
00108                         case LCHColorspace            : colorSpaceType = "LCH"; break;
00109                         case LMSColorspace            : colorSpaceType = "LMS"; break;
00110 #endif
00111 #if MagickLibVersion > 0x684
00112                         case LCHabColorspace          : colorSpaceType = "LCHab"; break;
00113                         case LCHuvColorspace          : colorSpaceType = "LCHuv"; break;
00114                         case scRGBColorspace          : colorSpaceType = "scRGB"; break;
00115                         case HSIColorspace            : colorSpaceType = "HSI"; break;
00116                         case HSVColorspace            : colorSpaceType = "HSV"; break;
00117                         case HCLpColorspace           : colorSpaceType = "HCLp"; break;
00118                         case YDbDrColorspace          : colorSpaceType = "YDbDr"; break;
00119 #endif
00120                 }
00121 
00122                 std::string interlaceType;
00123                 switch( image->interlace )
00124                 {
00125                         case UndefinedInterlace    : interlaceType = "undefined"; break;
00126                         case NoInterlace           : interlaceType = "no interlacing"; break;
00127                         case LineInterlace         : interlaceType = "line interlacing"; break;
00128                         case PlaneInterlace        : interlaceType = "plane interlacing"; break;
00129                         case PartitionInterlace    : interlaceType = "partition interlacing"; break;
00130                         case 5                     : interlaceType = "GIF interlacing"; break; // GIFInterlace
00131                         case 6                     : interlaceType = "Jpeg interlacing"; break; // JPEGInterlace
00132                         case 7                     : interlaceType = "PNG interlacing"; break; // PNGInterlace
00133                 }
00134 
00135                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "width"                 << image->columns                                                                         );
00136                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "height"                << image->rows                                                                            );
00137                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "bit-depth"             << image->depth  << " bits"                                                               );
00138                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "compression quality"   << image->quality                                                                         );
00139                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "image type"            << imageType                                                                              );
00140                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "" );
00141                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "x resolution"          << image->x_resolution  << resolutionType                                                 );
00142                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "y resolution"          << image->y_resolution  << resolutionType                                                 );
00143                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "interlacing"           << interlaceType                                                                          );
00144                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "" );
00145                 //TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "format"                << image->format()                                                                        );
00146                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "channels"              << colorSpaceType << ( GetImageAlphaChannel(image)==MagickTrue ? std::string("A") : "" )  );
00147                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "color space"           << colorSpaceType                                                                         );
00148                 TUTTLE_LOG_INFO( std::setw(FIRST_COLUMN_WIDTH) << "gamma"                 << image->gamma                                                                           );
00149 
00150                 TUTTLE_LOG_INFO( "" );
00151         }
00152         catch( ... )
00153         {
00154                 TUTTLE_LOG_ERROR( "Caught exception" << "\n" );
00155         }
00156         
00157 }
00158 
00159 void dumpImageProperties( const sequenceParser::File& s )
00160 {
00161         TUTTLE_LOG_INFO(s);
00162         printImageProperties( s.getAbsoluteFilename() );
00163         sam::wasSthgDumped = true;
00164 }
00165 
00166 void dumpImageProperties( const sequenceParser::Sequence& s )
00167 {
00168         TUTTLE_LOG_INFO(s);
00169         printImageProperties( s.getAbsoluteFirstFilename() );
00170         sam::wasSthgDumped = true;
00171 }
00172 
00173 
00174 void dumpImageProperties( boost::ptr_vector<sequenceParser::FileObject>& listing )
00175 {
00176         BOOST_FOREACH( const sequenceParser::FileObject& sequence, listing )
00177         {
00178                 switch( sequence.getMaskType () )
00179                 {
00180                         case sequenceParser::eMaskTypeSequence  : dumpImageProperties( static_cast<const sequenceParser::Sequence&>( sequence ) ); break;
00181                         case sequenceParser::eMaskTypeFile              : dumpImageProperties( static_cast<const sequenceParser::File&>( sequence ) ); break;
00182                         case sequenceParser::eMaskTypeDirectory : break;
00183                         case sequenceParser::eMaskTypeUndefined : break;
00184                 }
00185         }
00186         listing.clear();
00187 }
00188 
00189 
00190 int main( int argc, char** argv )
00191 {
00192         signal(SIGINT, signal_callback_handler);
00193 
00194         using namespace tuttle::common;
00195         using namespace sam;
00196         
00197         boost::shared_ptr<formatters::Formatter> formatter( formatters::Formatter::get() );
00198         boost::shared_ptr<Color>                 color( Color::get() );
00199 
00200         sequenceParser::EMaskType researchMask       = sequenceParser::eMaskTypeSequence; // by default show sequences
00201         sequenceParser::EMaskOptions descriptionMask = sequenceParser::eMaskOptionsColor; // by default show nothing
00202         bool recursiveListing = false;
00203         std::string availableExtensions;
00204         std::vector<std::string> paths;
00205         std::vector<std::string> filters;
00206 
00207         formatter->init_logging();
00208         
00209         // Declare the supported options.
00210         bpo::options_description mainOptions;
00211         mainOptions.add_options()
00212                 ( kAllOptionString, kAllOptionMessage )
00213                 ( kExpressionOptionString, bpo::value<std::string>(), kExpressionOptionMessage )
00214                 ( kFilesOptionString,      kFilesOptionMessage )
00215                 ( kHelpOptionString,       kHelpOptionMessage )
00216                 ( kIgnoreOptionString,     kIgnoreOptionMessage )
00217                 ( kPathOptionString,       kPathOptionMessage )
00218                 ( kRecursiveOptionString,  kRecursiveOptionMessage )
00219                 ( kVerboseOptionString,    bpo::value<int>()->default_value( 2 ), kVerboseOptionMessage )
00220                 ( kQuietOptionString,      kQuietOptionMessage )
00221                 ( kColorOptionString,      kColorOptionMessage )
00222                 ( kFirstImageOptionString, bpo::value<unsigned int>(), kFirstImageOptionMessage )
00223                 ( kLastImageOptionString,  bpo::value<unsigned int>(), kLastImageOptionMessage )
00224                 ( kBriefOptionString,      kBriefOptionMessage );
00225 
00226         // describe hidden options
00227         bpo::options_description hidden;
00228         hidden.add_options()
00229                 ( kInputDirOptionString, bpo::value< std::vector<std::string> >(), kInputDirOptionMessage )
00230                 ( kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage );
00231 
00232         // define default options
00233         bpo::positional_options_description pod;
00234         pod.add(kInputDirOptionLongName, -1);
00235 
00236         bpo::options_description cmdline_options;
00237         cmdline_options.add(mainOptions).add(hidden);
00238 
00239         bpo::positional_options_description pd;
00240         pd.add("", -1);
00241 
00242         //parse the command line, and put the result in vm
00243         bpo::variables_map vm;
00244 
00245         try
00246         {
00247                 //parse the command line, and put the result in vm
00248                 bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm);
00249 
00250                 // get environment options and parse them
00251                 if( const char* env_info_options = std::getenv("SAM_INFO_OPTIONS") )
00252                 {
00253                         const std::vector<std::string> envOptions = bpo::split_unix( env_info_options, " " );
00254                         bpo::store(bpo::command_line_parser(envOptions).options(cmdline_options).positional(pod).run(), vm);
00255                 }
00256                 if( const char* env_info_options = std::getenv("SAM_OPTIONS") )
00257                 {
00258                         const std::vector<std::string> envOptions = bpo::split_unix( env_info_options, " " );
00259                         bpo::store(bpo::command_line_parser(envOptions).options(cmdline_options).positional(pod).run(), vm);
00260                 }
00261                 bpo::notify(vm);
00262         }
00263         catch( const bpo::error& e)
00264         {
00265                 TUTTLE_LOG_ERROR( "error in command line: " << e.what() );
00266                 exit( 254 );
00267         }
00268         catch(...)
00269         {
00270                 TUTTLE_LOG_ERROR( "unknown error in command line." );
00271                 exit( 254 );
00272         }
00273 
00274         if( vm.count( kColorOptionLongName ) )
00275         {
00276                 color->enable();
00277         }
00278         
00279         if( vm.count( kEnableColorOptionLongName ) )
00280         {
00281                 const std::string str = vm[kEnableColorOptionLongName].as<std::string>();
00282                 if( string_to_boolean(str) )
00283                 {
00284                         color->enable();
00285                 }
00286                 else
00287                 {
00288                         color->disable();
00289                 }
00290         }
00291 
00292         if( vm.count( kHelpOptionLongName ) )
00293         {
00294                 TUTTLE_LOG_INFO( color->_blue  << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std );
00295                 TUTTLE_LOG_INFO( "" );
00296                 TUTTLE_LOG_INFO( color->_blue  << "NAME" << color->_std );
00297                 TUTTLE_LOG_INFO( color->_green << "\tsam-info - get informations about a sequence" << color->_std );
00298                 TUTTLE_LOG_INFO( "" );
00299                 TUTTLE_LOG_INFO( color->_blue  << "SYNOPSIS" << color->_std );
00300                 TUTTLE_LOG_INFO( color->_green << "\tsam-info [options] [sequences]" << color->_std );
00301                 TUTTLE_LOG_INFO( "" );
00302                 TUTTLE_LOG_INFO( color->_blue  << "DESCRIPTION\n" << color->_std );
00303                 TUTTLE_LOG_INFO( "Print informations from Sequence (or file) like resolution, colorspace, etc." );
00304                 TUTTLE_LOG_INFO( "" );
00305                 TUTTLE_LOG_INFO( color->_blue  << "OPTIONS" << color->_std);
00306                 TUTTLE_LOG_INFO( mainOptions );
00307                 TUTTLE_LOG_INFO( "" );
00308                 return 0;
00309         }
00310 
00311         if ( vm.count(kBriefOptionLongName) )
00312         {
00313                 TUTTLE_LOG_INFO( color->_green << "get informations about a sequence" << color->_std );
00314                 return 0;
00315         }
00316 
00317         if (vm.count(kExpressionOptionLongName))
00318         {
00319                 bal::split( filters, vm[kExpressionOptionLongName].as<std::string>(), bal::is_any_of(","));
00320         }
00321 
00322         if (vm.count(kDirectoriesOptionLongName))
00323         {
00324                 researchMask |= sequenceParser::eMaskTypeDirectory;
00325         }
00326 
00327         if (vm.count(kFilesOptionLongName))
00328         {
00329                 researchMask |= sequenceParser::eMaskTypeFile;
00330         }
00331 
00332         if (vm.count(kIgnoreOptionLongName))
00333         {
00334                 researchMask &= ~sequenceParser::eMaskTypeSequence;
00335         }
00336 
00337         switch( vm[ kVerboseOptionLongName ].as< int >() )
00338         {
00339                 case 0 :  formatter->setLogLevel( boost::log::trivial::trace   ); break;
00340                 case 1 :  formatter->setLogLevel( boost::log::trivial::debug   ); break;
00341                 case 2 :  formatter->setLogLevel( boost::log::trivial::info    ); break;
00342                 case 3 :  formatter->setLogLevel( boost::log::trivial::warning ); break;
00343                 case 4 :  formatter->setLogLevel( boost::log::trivial::error   ); break;
00344                 case 5 :  formatter->setLogLevel( boost::log::trivial::fatal   ); break;
00345                 default : formatter->setLogLevel( boost::log::trivial::warning ); break;
00346         }
00347         if( vm.count(kQuietOptionLongName) )
00348         {
00349                 formatter->setLogLevel( boost::log::trivial::fatal );
00350         }
00351 
00352         if (vm.count(kFirstImageOptionLongName))
00353         {
00354                 firstImage  = vm[kFirstImageOptionLongName].as< unsigned int >();
00355         }
00356 
00357         if (vm.count(kLastImageOptionLongName))
00358         {
00359                 lastImage  = vm[kLastImageOptionLongName].as< unsigned int >();
00360         }
00361 
00362         if (vm.count(kFullRMPathOptionLongName))
00363         {
00364                 researchMask |= sequenceParser::eMaskTypeDirectory;
00365                 researchMask |= sequenceParser::eMaskTypeFile;
00366                 researchMask |= sequenceParser::eMaskTypeSequence;
00367         }
00368 
00369         if (vm.count(kAllOptionLongName))
00370         {
00371                 // add .* files
00372                 descriptionMask |= sequenceParser::eMaskOptionsDotFile;
00373         }
00374 
00375         if (vm.count(kPathOptionLongName))
00376         {
00377                  descriptionMask |= sequenceParser::eMaskOptionsPath;
00378         }
00379 
00380         // defines paths, but if no directory specify in command line, we add the current path
00381         if (vm.count(kInputDirOptionLongName))
00382         {
00383                 paths = vm[kInputDirOptionLongName].as< std::vector<std::string> >();
00384         }
00385         else
00386         {
00387                 paths.push_back( "./" );
00388         }
00389 
00390         if (vm.count(kRecursiveOptionLongName))
00391         {
00392                 recursiveListing = true;
00393         }
00394 //      for(unsigned int i=0; i<filters.size(); i++)
00395 //      TUTTLE_LOG_TRACE( "filters = " << filters.at(i) );
00396 //      TUTTLE_LOG_TRACE( "research mask = " << researchMask );
00397 //      TUTTLE_LOG_TRACE( "options  mask = " << descriptionMask );
00398 
00399 
00400         try
00401         {
00402                 std::vector<boost::filesystem::path> pathsNoRemoved;
00403                 
00404                 BOOST_FOREACH( bfs::path path, paths )
00405                 {
00406 //                      TUTTLE_LOG_TRACE( "path: "<< path );
00407                         if( bfs::exists( path ) )
00408                         {
00409                                 if( bfs::is_directory( path ) )
00410                                 {
00411 //                                      TUTTLE_LOG_TRACE( "is a directory" );
00412                                         if( recursiveListing )
00413                                         {
00414                                                 for ( bfs::recursive_directory_iterator end, dir(path); dir != end; ++dir )
00415                                                 {
00416                                                         if( bfs::is_directory( *dir ) )
00417                                                         {
00418 //                                                              TUTTLE_LOG_TRACE *dir );
00419                                                                 boost::ptr_vector<sequenceParser::FileObject> listing = sequenceParser::fileObjectInDirectory( ( (bfs::path)*dir ).string() , filters, researchMask, descriptionMask );
00420                                                                 dumpImageProperties( listing );
00421                                                         }
00422                                                 }
00423                                         }
00424                                         boost::ptr_vector<sequenceParser::FileObject> listing = sequenceParser::fileObjectInDirectory( path.string(), filters, researchMask, descriptionMask );
00425                                         dumpImageProperties( listing );
00426                                 }
00427                                 else
00428                                 {
00429                                         if( std::strcmp( path.branch_path().string().c_str(),"" ) == 0 )
00430                                                 path = "."/path.leaf();
00431                                         //TUTTLE_LOG_TRACE( "is NOT a directory "<< path.branch_path() << " | "<< path.leaf() );
00432                                         filters.push_back( path.leaf().string() );
00433                                         boost::ptr_vector<sequenceParser::FileObject> listing = sequenceParser::fileObjectInDirectory( path.branch_path().string(), filters, researchMask, descriptionMask );
00434                                         dumpImageProperties( listing );
00435                                         filters.pop_back( );
00436                                 }
00437                         }
00438                         else
00439                         {
00440 //                              TUTTLE_LOG_TRACE( "not exist ...." );
00441                                 try
00442                                 {
00443                                         sequenceParser::Sequence s(path.branch_path(), descriptionMask );
00444                                         s.initFromDetection( path.string(), sequenceParser::Sequence::ePatternDefault );
00445                                         if( s.getNbFiles() )
00446                                         {
00447                                                 //TUTTLE_LOG_TRACE(s);
00448                                                 dumpImageProperties( s );
00449                                         }
00450                                 }
00451                                 catch(... )
00452                                 {
00453                                         TUTTLE_LOG_ERROR( "Unrecognized pattern \"" << path << "\"" );
00454                                 }
00455                         }
00456                 }
00457         }
00458         catch (bfs::filesystem_error &ex)
00459         {
00460                 TUTTLE_LOG_ERROR( ex.what() );
00461         }
00462         catch(... )
00463         {
00464                 TUTTLE_LOG_ERROR( boost::current_exception_diagnostic_information() );
00465         }
00466         
00467         if( !wasSthgDumped )
00468         {
00469                 TUTTLE_LOG_ERROR( "No sequence found here." );
00470         }
00471         
00472         return 0;
00473 }
00474