core/vul/vul_sequence_filename_map.cxx
Go to the documentation of this file.
00001 // This is core/vul/vul_sequence_filename_map.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 
00006 // Author: David Capel, Oxford RRG
00007 // Created: 15 April 2000
00008 //
00009 //-----------------------------------------------------------------------------
00010 
00011 #include "vul_sequence_filename_map.h"
00012 #include <vcl_cstddef.h> // for vcl_size_t
00013 #include <vcl_cstdlib.h>
00014 #include <vcl_iostream.h>
00015 #include <vcl_string.h>
00016 
00017 #include <vul/vul_sprintf.h>
00018 #include <vul/vul_reg_exp.h>
00019 #include <vul/vul_file_iterator.h>
00020 
00021 const bool debug = 0;
00022 
00023 static struct
00024 {
00025   char const * image_dir;
00026   char const * extension;
00027 } dir_ext_pairs[] = { {"pgm/",".pgm"},
00028                       {"ppm/",".ppm"},
00029                       {"jpg/",".jpg"},
00030                       {"jpg/",".jpeg"},
00031                       {"jpeg/",".jpg"},
00032                       {"jpeg/",".jpeg"},
00033                       {"tiff/",".tiff"},
00034                       {"mit/",".mit"},
00035                       {"viff/",".viff"},
00036                       {"rgb/",".rgb"} };
00037 
00038 const int num_dir_ext_pairs = sizeof(dir_ext_pairs) / sizeof(dir_ext_pairs[0]);
00039 
00040 // Empty constructor to allow the operator= to be used later.
00041 vul_sequence_filename_map::vul_sequence_filename_map ()
00042   : start_(-1), step_(-1), end_(-1)
00043 {
00044 }
00045 
00046 vul_sequence_filename_map::vul_sequence_filename_map (vcl_string const & seq_template, vcl_vector<int> const & indices)
00047   : seq_template_(seq_template), indices_(indices), start_(-1), step_(-1), end_(-1)
00048 {
00049   parse();
00050 }
00051 
00052 vul_sequence_filename_map::vul_sequence_filename_map (vcl_string const & seq_template, int start, int end, int step)
00053   : seq_template_(seq_template), start_(start), step_(step), end_(end)
00054 {
00055   for (int i=start; i <= end; i+=step)
00056     indices_.push_back(i);
00057   parse();
00058 }
00059 
00060 vul_sequence_filename_map::vul_sequence_filename_map (vcl_string const & seq_template, int step)
00061   : seq_template_(seq_template), start_(-1), step_(step), end_(-1)
00062 {
00063   parse();
00064 }
00065 
00066 vul_sequence_filename_map::~vul_sequence_filename_map()
00067 {
00068 }
00069 
00070 vcl_string vul_sequence_filename_map::name(int frame)
00071 {
00072   vcl_string index_str = vul_sprintf(index_format_.c_str(), indices_[frame]);
00073   return basename_ + index_str;
00074 }
00075 
00076 vcl_string vul_sequence_filename_map::pair_name (int i, int j)
00077 {
00078   vcl_string index_str = vul_sprintf((index_format_ + "." + index_format_).c_str(), indices_[i], indices_[j]);
00079   return basename_ + index_str;
00080 }
00081 
00082 vcl_string vul_sequence_filename_map::triplet_name (int i, int j, int k)
00083 {
00084   vcl_string index_str = vul_sprintf((index_format_ + "." +
00085     index_format_ + "." + index_format_).c_str(), indices_[i],
00086     indices_[j], indices_[k]);
00087   return basename_ + index_str;
00088 }
00089 
00090 void vul_sequence_filename_map::parse()
00091 {
00092   vcl_string temp = seq_template_;
00093 
00094   // Search for trailing index spec -   "img.%03d.pgm,0:1:10" , "ppm/img*;:5:"
00095   {
00096     vul_reg_exp re("[,;]([0-9]+)?(:[0-9]+)?:([0-9]+)?$");
00097     if (re.find(temp.c_str()))
00098     {
00099       vcl_string match_start = re.match(1);
00100       vcl_string match_step = re.match(2);
00101       vcl_string match_end = re.match(3);
00102 
00103       temp.erase(re.start(0));
00104 
00105       if (match_start.length() > 0)
00106         start_ = vcl_atoi(match_start.c_str());
00107 
00108       if (match_step.length() > 0)
00109         step_ = vcl_atoi(match_step.c_str()+1);
00110 
00111       if (match_end.length() > 0)
00112         end_ = vcl_atoi(match_end.c_str());
00113     }
00114   }
00115   // Search for image extension
00116   {
00117     vul_reg_exp re("\\.([a-zA-Z_0-9]+)$");
00118     if (re.find(temp.c_str())) {
00119       image_extension_ = re.match(0);
00120       temp.erase(re.start(0));
00121     }
00122   }
00123   // Search for basename template
00124   {
00125     vul_reg_exp re("([a-zA-Z0-9_%#\\.]+)$");
00126     vcl_string bt;
00127     if (re.find(temp.c_str())) {
00128       bt = re.match(0);
00129       temp.erase(re.start(0));
00130     }
00131     // This should have the form "img.%03d" or "img.###". Split it into basename and index format
00132     vcl_size_t pos;
00133     if ( (pos = bt.find('%')) != vcl_string::npos)
00134       index_format_ = bt.substr(pos);
00135     else if ( (pos = bt.find('#')) != vcl_string::npos) {
00136       vcl_size_t last_pos = bt.rfind('#');
00137       index_format_ = vul_sprintf("0%id",last_pos - pos + 1);
00138       index_format_ = "%" + index_format_;
00139     }
00140     else
00141       index_format_ = "%03d";
00142     basename_ = bt.substr(0,pos);
00143   }
00144   // What remains must be the directory
00145   image_dir_ = temp;
00146 
00147   // Now to fill in any blanks
00148   //
00149   // Image dir and extension both blank :
00150   //  1 - Look in cwd for basename-compatible files with common image extensions
00151   //  2 - Look for basename-compatible files in common image dirs with corresponding image extensions
00152   if (image_dir_ == "" && image_extension_ == "")
00153   {
00154     bool found_match = false;
00155     {
00156       vul_file_iterator fn("./*");
00157       for (;!found_match && bool(fn); ++fn)
00158         for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
00159           if (filter_dirent(fn(), dir_ext_pairs[i].extension)) {
00160             image_dir_ = "./";
00161             image_extension_ = dir_ext_pairs[i].extension;
00162             found_match = true;
00163           }
00164     }
00165     if (!found_match)
00166       for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
00167         vcl_string glob(dir_ext_pairs[i].image_dir);
00168         glob += "/*";
00169         vul_file_iterator fn(glob);
00170         for (;!found_match && bool(fn);++fn)
00171           if (filter_dirent(fn(), dir_ext_pairs[i].extension)) {
00172             image_dir_ = dir_ext_pairs[i].image_dir;
00173             image_extension_ = dir_ext_pairs[i].extension;
00174             found_match = true;
00175           }
00176       }
00177     if (!found_match) {
00178       vcl_cerr << __FILE__ << " : Can't find files matching " << basename_
00179                << index_format_ << " in common locations with common format!\n";
00180       vcl_abort();
00181     }
00182   }
00183 
00184   // Only image dir is blank :
00185   //  1 - Look for basename-compatible files in cwd
00186   //  2 - Look for basename-compatible files in dir corresponding to given image extension
00187   //  3 - Look for basename-compatible files in common image dirs
00188   else if (image_dir_ == "")
00189   {
00190     bool found_match = false;
00191     {
00192       for (vul_file_iterator fn("./*"); !found_match && bool(fn); ++fn)
00193         if (filter_dirent(fn.filename(), image_extension_)) {
00194           image_dir_ = "./";
00195           found_match = true;
00196         }
00197     }
00198 
00199     if (!found_match) {
00200       for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
00201         if (vcl_string(dir_ext_pairs[i].extension) == image_extension_) {
00202           vcl_string glob(dir_ext_pairs[i].image_dir); glob += "*";
00203           for (vul_file_iterator fn(glob); !found_match && bool(fn); ++fn)
00204             if (filter_dirent(fn.filename(), image_extension_)) {
00205               image_dir_ = dir_ext_pairs[i].image_dir;
00206               found_match = true;
00207             }
00208         }
00209     }
00210 
00211     if (!found_match) {
00212       for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
00213         vcl_string glob(dir_ext_pairs[i].image_dir); glob += "*";
00214         for (vul_file_iterator fn(glob); !found_match && bool(fn); ++fn)
00215           if (filter_dirent(fn.filename(), image_extension_)) {
00216             image_dir_ = dir_ext_pairs[i].image_dir;
00217             found_match = true;
00218           }
00219       }
00220     }
00221 
00222     if (!found_match) {
00223       vcl_cerr << __FILE__ << " : Can't find files matching " << basename_
00224                << index_format_<<image_extension_ << " in common locations!\n";
00225       vcl_abort();
00226     }
00227   }
00228 
00229   // Only extension is blank :
00230   //  1 - Look in image dir for basename-compatible files with extension corresponding to the image dir
00231   //  2 - Look in image dir for basename-compatible files with common image extensions
00232   else if (image_extension_ == "")
00233   {
00234     bool found_match = false;
00235     {
00236       vcl_string glob(image_dir_ + "*");
00237       vul_file_iterator fn(glob);
00238       if (fn) {
00239         for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
00240           if (vcl_string(dir_ext_pairs[i].image_dir) == image_dir_) {
00241             for (;!found_match && bool(fn);++fn)
00242               if (filter_dirent(fn.filename(), dir_ext_pairs[i].extension)) {
00243                 image_extension_ = dir_ext_pairs[i].extension;
00244                 found_match = true;
00245               }
00246           }
00247       }
00248     }
00249 
00250     if (!found_match) {
00251       vul_file_iterator fn(image_dir_);
00252       if (fn) {
00253         for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
00254           for (;!found_match && bool(fn); ++fn)
00255             if (filter_dirent(fn.filename(), dir_ext_pairs[i].extension)) {
00256               image_extension_ = dir_ext_pairs[i].extension;
00257               found_match = true;
00258             }
00259         }
00260       }
00261     }
00262 
00263     if (!found_match) {
00264       vcl_cerr << __FILE__ << " : Can't find files matching " << image_dir_
00265                << basename_ << index_format_ << " with common extension!\n";
00266       vcl_abort();
00267     }
00268   }
00269 
00270   // Start and/or end is not specified :
00271   //   Find all basename-compatible files and set sequence indices accordingly
00272   if (indices_.size() == 0)
00273   {
00274     // See if we need to scan the image directory to get the sequence start/end
00275     if (start_ == -1 || end_ == -1) {
00276       int max = -1000000;
00277       int min = 1000000;
00278       for (vul_file_iterator fn(image_dir_ + "*");fn;++fn)
00279         if (filter_dirent(fn.filename(), image_extension_)) {
00280           int index = extract_index(fn.filename());
00281           max = (index > max) ? index : max;
00282           min = (index < min) ? index : min;
00283         }
00284       if (max < min) {
00285         vcl_cerr << "vul_sequence_filename_map: WARNING: no files in " << image_dir_ << vcl_endl;
00286       }
00287 
00288       if (start_ == -1) start_ = min;
00289       if (end_ == -1) end_ = max;
00290     }
00291     for (int i=start_; i <=  end_; i = i+step_)
00292       indices_.push_back(i);
00293   }
00294 
00295   if (debug)
00296     vcl_cerr << seq_template_ << vcl_endl
00297              << "    image dir : " << image_dir_ << vcl_endl
00298              << "    basename  : " << basename_ << vcl_endl
00299              << " index format : " << index_format_ << vcl_endl
00300              << "    extension : " << image_extension_ << vcl_endl
00301              << "    indices   : " << start_ << ':' << step_ << ':' << end_
00302              << vcl_endl << vcl_endl;
00303 }
00304 
00305 int vul_sequence_filename_map::get_mapped_index(int real) const
00306 {
00307   int idx = -1;
00308   for (int i=0; i < int(indices_.size()); ++i)
00309     if (indices_[i] == real) {
00310       idx = i;
00311       break;
00312     }
00313   return idx;
00314 }
00315 
00316 
00317 vcl_ostream& vul_sequence_filename_map::print (vcl_ostream& s) const
00318 {
00319   s << "vul_sequence_filename_map : " << image_dir_ << basename_
00320     << index_format_ << image_extension_ << " [" << indices_[0] << ':'
00321     << indices_[1] - indices_[0] << ':' << indices_.back() << "]\n";
00322 
00323 #if 0
00324   s << vul_sprintf("vul_sequence_filename_map : %s%s%s [%i:%i:%i]",
00325                    image_dir_.c_str(), basename_.c_str(), index_format_.c_str(), image_extension_.c_str(),
00326                    indices_[0], indices_[1] - indices_[0], indices_.back());
00327 #endif
00328   return s;
00329 }
00330 
00331 bool vul_sequence_filename_map::filter_dirent(char const* name_string, vcl_string const& extension)
00332 {
00333   static vcl_size_t expected_length = 0L;
00334   if (expected_length == 0L)
00335     expected_length = basename_.size() +
00336                       (vcl_string(vul_sprintf(index_format_.c_str(),0)) + extension).size();
00337 
00338   vcl_string name_str(name_string);
00339 
00340   return name_str.size() == expected_length
00341       && name_str.substr(0,basename_.size()) == basename_
00342       && name_str.substr(expected_length-extension.size(), vcl_string::npos) == extension;
00343 }
00344 
00345 int vul_sequence_filename_map::extract_index(char const* name_string)
00346 {
00347   vcl_string name_str(name_string);
00348   vcl_string index_str = name_str.substr(basename_.size(), name_str.size() - image_extension_.size());
00349   return vcl_atoi(index_str.c_str());
00350 }
00351 
00352 vcl_ostream& operator<<(vcl_ostream &os, const vul_sequence_filename_map& s)
00353 {
00354   return s.print(os);
00355 }