TuttleOFX
1
|
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