TuttleOFX
1
|
00001 #include <sam/common/utility.hpp> 00002 #include <sam/common/options.hpp> 00003 00004 #include <tuttle/host/Graph.hpp> 00005 00006 #include <detector.hpp> 00007 00008 #include <boost/filesystem.hpp> 00009 #include <boost/program_options.hpp> 00010 00011 using namespace tuttle::host; 00012 namespace bfs = boost::filesystem; 00013 namespace bpo = boost::program_options; 00014 00015 00016 static int _blackImage = 0; 00017 static int _nullFileSize = 0; 00018 static int _corruptedImage = 0; 00019 static int _missingFiles = 0; 00020 enum EReturnCode 00021 { 00022 eReturnCodeOK = 0, 00023 eReturnCodeErrorInImages = 1, 00024 eReturnCodeApplicationError = 2 00025 }; 00026 00027 enum EImageStatus 00028 { 00029 eImageStatusOK, 00030 eImageStatusBlack, 00031 eImageStatusFileSizeError, 00032 eImageStatusNoFile, 00033 eImageStatusImageError 00034 }; 00035 00036 /** 00037 * @brief Check the image status. 00038 */ 00039 EImageStatus checkImageStatus( Graph::Node& read, Graph::Node& stat, Graph& graph, const bfs::path& filename ) 00040 { 00041 if( bfs::exists( filename ) == 0 ) 00042 return eImageStatusNoFile; 00043 00044 if( bfs::file_size( filename ) == 0 ) 00045 return eImageStatusFileSizeError; 00046 00047 try 00048 { 00049 // Setup parameters 00050 read.getParam( "filename" ).setValue( filename.string() ); 00051 graph.compute( stat ); 00052 00053 for( unsigned int i = 0; i<4; ++i ) 00054 { 00055 if( stat.getParam( "outputChannelMax" ).getDoubleValueAtIndex(i) != 0 ) 00056 return eImageStatusOK; 00057 if( stat.getParam( "outputChannelMin" ).getDoubleValueAtIndex(i) != 0 ) 00058 return eImageStatusOK; 00059 } 00060 TUTTLE_LOG_INFO( "stat:" << stat ); 00061 return eImageStatusBlack; 00062 } 00063 catch( ... ) 00064 { 00065 return eImageStatusImageError; 00066 } 00067 } 00068 00069 EImageStatus checkFile( Graph::Node& read, Graph::Node& stat, Graph& graph, const bfs::path& filename ) 00070 { 00071 EImageStatus s = checkImageStatus( read, stat, graph, filename ); 00072 00073 std::string message = ""; 00074 switch( s ) 00075 { 00076 case eImageStatusOK: 00077 break; 00078 case eImageStatusBlack: 00079 message = "Black image: "; 00080 ++_blackImage; 00081 break; 00082 case eImageStatusFileSizeError: 00083 message = "Null file size: "; 00084 ++_nullFileSize; 00085 break; 00086 case eImageStatusNoFile: 00087 message = "Missing file: "; 00088 ++_missingFiles; 00089 break; 00090 case eImageStatusImageError: 00091 message = "Corrupted image: "; 00092 ++_corruptedImage; 00093 break; 00094 } 00095 TUTTLE_LOG_INFO( message << filename ); 00096 return s; 00097 } 00098 00099 void checkSequence( Graph::Node& read, Graph::Node& stat, Graph& graph, const sequenceParser::Sequence& seq ) 00100 { 00101 for( sequenceParser::Time t = seq.getFirstTime(); t <= seq.getLastTime(); ++t ) 00102 { 00103 checkFile( read, stat, graph, seq.getAbsoluteFilenameAt(t) ); 00104 } 00105 } 00106 00107 void checkSequence( Graph::Node& read, Graph::Node& stat, Graph& graph, const sequenceParser::Sequence& seq, const sequenceParser::Time first, const sequenceParser::Time last ) 00108 { 00109 for( sequenceParser::Time t = first; t <= last; ++t ) 00110 { 00111 checkFile( read, stat, graph, seq.getAbsoluteFilenameAt(t) ); 00112 } 00113 } 00114 00115 int main( int argc, char** argv ) 00116 { 00117 signal(SIGINT, signal_callback_handler); 00118 00119 using namespace tuttle::common; 00120 using namespace sam; 00121 00122 boost::shared_ptr<formatters::Formatter> formatter( formatters::Formatter::get() ); 00123 boost::shared_ptr<Color> color( Color::get() ); 00124 00125 std::vector<std::string> inputs; 00126 std::string readerId; 00127 bool hasRange = false; 00128 bool script = false; 00129 std::vector<int> range; 00130 00131 bpo::options_description desc; 00132 bpo::options_description hidden; 00133 00134 formatter->init_logging(); 00135 00136 desc.add_options() 00137 ( kHelpOptionString, kHelpOptionMessage ) 00138 ( kReaderOptionString, bpo::value(&readerId)/*->required()*/, kReaderOptionMessage ) 00139 ( kInputOptionString, bpo::value(&inputs)/*->required()*/,kInputOptionMessage ) 00140 ( kRangeOptionString, bpo::value(&range)->multitoken(), kRangeOptionMessage ) 00141 ( kBriefOptionString, kBriefOptionMessage ) 00142 ( kColorOptionString, kColorOptionMessage ) 00143 ( kScriptOptionString, kScriptOptionMessage ); 00144 00145 // describe hidden options 00146 hidden.add_options() 00147 ( kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage ); 00148 00149 bpo::options_description cmdline_options; 00150 cmdline_options.add( desc ).add( hidden ); 00151 00152 bpo::positional_options_description pod; 00153 pod.add(kInputOptionLongName, -1); 00154 00155 bpo::variables_map vm; 00156 00157 try 00158 { 00159 //parse the command line, and put the result in vm 00160 bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm); 00161 00162 // get environment options and parse them 00163 if( const char* env_check_options = std::getenv( "SAM_CHECK_OPTIONS" ) ) 00164 { 00165 const std::vector<std::string> vecOptions = bpo::split_unix( env_check_options, " " ); 00166 bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); 00167 } 00168 if( const char* env_check_options = std::getenv( "SAM_OPTIONS" ) ) 00169 { 00170 const std::vector<std::string> vecOptions = bpo::split_unix( env_check_options, " " ); 00171 bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); 00172 } 00173 bpo::notify(vm); 00174 } 00175 catch( const bpo::error& e) 00176 { 00177 TUTTLE_LOG_ERROR( "sam-check: command line error: " << e.what() ); 00178 exit( 254 ); 00179 } 00180 catch(...) 00181 { 00182 TUTTLE_LOG_ERROR( "sam-check: unknown error in command line." ); 00183 exit( 254 ); 00184 } 00185 00186 if( vm.count( kScriptOptionLongName ) ) 00187 { 00188 // disable color, disable directory printing and set relative path by default 00189 script = true; 00190 } 00191 00192 if( vm.count( kColorOptionLongName ) ) 00193 { 00194 color->enable(); 00195 } 00196 00197 if( vm.count( kEnableColorOptionLongName ) ) 00198 { 00199 const std::string str = vm[kEnableColorOptionLongName].as<std::string>(); 00200 if( string_to_boolean(str) ) 00201 { 00202 color->enable(); 00203 } 00204 else 00205 { 00206 color->disable(); 00207 } 00208 } 00209 00210 if( vm.count(kBriefOptionLongName) ) 00211 { 00212 TUTTLE_LOG_INFO( color->_green << "check image files" << color->_std ); 00213 std::cout.rdbuf(0); 00214 return 0; 00215 } 00216 00217 if( vm.count(kHelpOptionLongName) || vm.count(kInputDirOptionLongName) == 0 ) 00218 { 00219 TUTTLE_LOG_INFO( color->_blue << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std ); 00220 TUTTLE_LOG_INFO( "" ); 00221 TUTTLE_LOG_INFO( color->_blue << "NAME" << color->_std ); 00222 TUTTLE_LOG_INFO( color->_green << "\tsam-check - detect black images in sequences" << color->_std ); 00223 TUTTLE_LOG_INFO( "" ); 00224 TUTTLE_LOG_INFO( color->_blue << "SYNOPSIS" << color->_std ); 00225 TUTTLE_LOG_INFO( color->_green << "\tsam-check [reader] [input] [options]" << color->_std ); 00226 TUTTLE_LOG_INFO( "" ); 00227 TUTTLE_LOG_INFO( color->_blue << "DESCRIPTION" << color->_std << std::endl ); 00228 TUTTLE_LOG_INFO( "" ); 00229 00230 TUTTLE_LOG_INFO( "Check if sequence have black images." ); 00231 TUTTLE_LOG_INFO( "This tools process the PSNR of an image, and if it's null, the image is considered black." ); 00232 00233 TUTTLE_LOG_INFO( color->_blue << "OPTIONS" << color->_std ); 00234 TUTTLE_LOG_INFO( "" ); 00235 TUTTLE_LOG_INFO( desc ); 00236 return 0; 00237 } 00238 if( !vm.count(kReaderOptionLongName) ) 00239 { 00240 TUTTLE_LOG_ERROR( "sam-check : no reader specified." ); 00241 TUTTLE_LOG_ERROR( " run sam-check -h for more information." ); 00242 return 0; 00243 } 00244 if( !vm.count(kInputOptionLongName) ) 00245 { 00246 TUTTLE_LOG_ERROR( "sam-check : no input specified." ); 00247 TUTTLE_LOG_ERROR( " run sam-check -h for more information." ); 00248 return 0; 00249 } 00250 00251 readerId = vm[kReaderOptionLongName].as<std::string>(); 00252 inputs = vm[kInputOptionLongName].as< std::vector<std::string> >(); 00253 00254 if( vm.count(kRangeOptionLongName) ) 00255 { 00256 range = vm[kRangeOptionLongName].as< std::vector<int> >(); 00257 hasRange = ( range.size() == 2 ); 00258 } 00259 00260 try 00261 { 00262 core().preload(); 00263 Graph graph; 00264 Graph::Node& read = graph.createNode( readerId ); 00265 Graph::Node& stat = graph.createNode( "tuttle.imagestatistics" ); 00266 read.getParam("explicitConversion").setValue(3); // force reader to use float image buffer 00267 graph.connect( read, stat ); 00268 00269 BOOST_FOREACH( const bfs::path path, inputs ) 00270 { 00271 if( bfs::exists( path ) ) 00272 { 00273 if( bfs::is_directory( path ) ) 00274 { 00275 boost::ptr_vector<sequenceParser::FileObject> fObjects; 00276 00277 fObjects = sequenceParser::fileObjectInDirectory( path.string() ); 00278 BOOST_FOREACH( sequenceParser::FileObject& fObj, fObjects ) 00279 { 00280 switch( fObj.getMaskType() ) 00281 { 00282 case sequenceParser::eMaskTypeSequence: 00283 { 00284 checkSequence( read, stat, graph, dynamic_cast<const sequenceParser::Sequence&>( fObj ) ); 00285 break; 00286 } 00287 case sequenceParser::eMaskTypeFile: 00288 { 00289 const sequenceParser::File fFile = dynamic_cast<const sequenceParser::File&>( fObj ); 00290 checkFile( read, stat, graph, fFile.getAbsoluteFilename() ); 00291 break; 00292 } 00293 case sequenceParser::eMaskTypeDirectory: 00294 case sequenceParser::eMaskTypeUndefined: 00295 break; 00296 } 00297 } 00298 } 00299 else 00300 { 00301 checkFile( read, stat, graph, path ); 00302 } 00303 } 00304 else 00305 { 00306 try 00307 { 00308 sequenceParser::Sequence s( path ); 00309 if( hasRange ) 00310 { 00311 checkSequence( read, stat, graph, s, range[0], range[1] ); 00312 } 00313 else 00314 { 00315 checkSequence( read, stat, graph, s ); 00316 } 00317 } 00318 catch( ... ) 00319 { 00320 TUTTLE_LOG_ERROR( "Unrecognized pattern \"" << path << "\"" ); 00321 return eReturnCodeApplicationError; 00322 } 00323 } 00324 } 00325 } 00326 catch( ... ) 00327 { 00328 TUTTLE_LOG_ERROR( boost::current_exception_diagnostic_information() ); 00329 return 255; 00330 } 00331 TUTTLE_LOG_WARNING( "________________________________________" ); 00332 TUTTLE_LOG_WARNING( "Black images: " << _blackImage ); 00333 TUTTLE_LOG_WARNING( "Null file size: " << _nullFileSize ); 00334 TUTTLE_LOG_WARNING( "Corrupted images: " << _corruptedImage ); 00335 TUTTLE_LOG_WARNING( "Holes in sequence: " << _missingFiles ); 00336 TUTTLE_LOG_WARNING( "________________________________________" ); 00337 00338 return _blackImage + _nullFileSize + _corruptedImage + _missingFiles; 00339 } 00340