vul_sequence_filename_map.cxx
Go to the documentation of this file.
1 // This is core/vul/vul_sequence_filename_map.cxx
2 
3 // Author: David Capel, Oxford RRG
4 // Created: 15 April 2000
5 //
6 //-----------------------------------------------------------------------------
7 
8 #include <cstddef>
9 #include <cstdlib>
10 #include <iostream>
11 #include <string>
12 #include <utility>
14 #ifdef _MSC_VER
15 # include <vcl_msvc_warnings.h>
16 #endif
17 
18 #include <vul/vul_sprintf.h>
19 #include <vul/vul_reg_exp.h>
20 #include <vul/vul_file_iterator.h>
21 
22 constexpr bool debug = false;
23 
24 static struct
25 {
26  char const * image_dir;
27  char const * extension;
28 } dir_ext_pairs[] = { {"pgm/",".pgm"},
29  {"ppm/",".ppm"},
30  {"jpg/",".jpg"},
31  {"jpg/",".jpeg"},
32  {"jpeg/",".jpg"},
33  {"jpeg/",".jpeg"},
34  {"tiff/",".tiff"},
35  {"mit/",".mit"},
36  {"viff/",".viff"},
37  {"rgb/",".rgb"} };
38 
39 const int num_dir_ext_pairs = sizeof(dir_ext_pairs) / sizeof(dir_ext_pairs[0]);
40 
41 // Empty constructor to allow the operator= to be used later.
43  : start_(-1), step_(-1), end_(-1)
44 {
45 }
46 
47 vul_sequence_filename_map::vul_sequence_filename_map (std::string seq_template, std::vector<int> indices)
48  : seq_template_(std::move(seq_template)), indices_(std::move(indices)), start_(-1), step_(-1), end_(-1)
49 {
50  parse();
51 }
52 
53 vul_sequence_filename_map::vul_sequence_filename_map (std::string seq_template, int start, int end, int step)
54  : seq_template_(std::move(seq_template)), start_(start), step_(step), end_(end)
55 {
56  for (int i=start; i <= end; i+=step)
57  indices_.push_back(i);
58  parse();
59 }
60 
61 vul_sequence_filename_map::vul_sequence_filename_map (std::string seq_template, int step)
62  : seq_template_(std::move(seq_template)), start_(-1), step_(step), end_(-1)
63 {
64  parse();
65 }
66 
68 
69 std::string vul_sequence_filename_map::name(int frame)
70 {
71  std::string index_str = vul_sprintf(index_format_.c_str(), indices_[frame]);
72  return basename_ + index_str;
73 }
74 
75 std::string vul_sequence_filename_map::pair_name (int i, int j)
76 {
77  std::string index_str = vul_sprintf((index_format_ + "." + index_format_).c_str(), indices_[i], indices_[j]);
78  return basename_ + index_str;
79 }
80 
81 std::string vul_sequence_filename_map::triplet_name (int i, int j, int k)
82 {
83  std::string index_str = vul_sprintf((index_format_ + "." +
84  index_format_ + "." + index_format_).c_str(), indices_[i],
85  indices_[j], indices_[k]);
86  return basename_ + index_str;
87 }
88 
90 {
91  std::string temp = seq_template_;
92 
93  // Search for trailing index spec - "img.%03d.pgm,0:1:10" , "ppm/img*;:5:"
94  {
95  vul_reg_exp re("[,;]([0-9]+)?(:[0-9]+)?:([0-9]+)?$");
96  if (re.find(temp.c_str()))
97  {
98  std::string match_start = re.match(1);
99  std::string match_step = re.match(2);
100  std::string match_end = re.match(3);
101 
102  temp.erase(re.start(0));
103 
104  if (match_start.length() > 0)
105  start_ = std::atoi(match_start.c_str());
106 
107  if (match_step.length() > 0)
108  step_ = std::atoi(match_step.c_str()+1);
109 
110  if (match_end.length() > 0)
111  end_ = std::atoi(match_end.c_str());
112  }
113  }
114  // Search for image extension
115  {
116  vul_reg_exp re("\\.([a-zA-Z_0-9]+)$");
117  if (re.find(temp.c_str())) {
118  image_extension_ = re.match(0);
119  temp.erase(re.start(0));
120  }
121  }
122  // Search for basename template
123  {
124  vul_reg_exp re("([a-zA-Z0-9_%#\\.]+)$");
125  std::string bt;
126  if (re.find(temp.c_str())) {
127  bt = re.match(0);
128  temp.erase(re.start(0));
129  }
130  // This should have the form "img.%03d" or "img.###". Split it into basename and index format
131  std::size_t pos;
132  if ( (pos = bt.find('%')) != std::string::npos)
133  index_format_ = bt.substr(pos);
134  else if ( (pos = bt.find('#')) != std::string::npos) {
135  std::size_t last_pos = bt.rfind('#');
136  index_format_ = vul_sprintf("0%id",last_pos - pos + 1);
138  }
139  else
140  index_format_ = "%03d";
141  basename_ = bt.substr(0,pos);
142  }
143  // What remains must be the directory
144  image_dir_ = temp;
145 
146  // Now to fill in any blanks
147  //
148  // Image dir and extension both blank :
149  // 1 - Look in cwd for basename-compatible files with common image extensions
150  // 2 - Look for basename-compatible files in common image dirs with corresponding image extensions
151  if (image_dir_ == "" && image_extension_ == "")
152  {
153  bool found_match = false;
154  {
155  vul_file_iterator fn("./*");
156  for (;!found_match && bool(fn); ++fn)
157  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
158  if (filter_dirent(fn(), dir_ext_pairs[i].extension)) {
159  image_dir_ = "./";
160  image_extension_ = dir_ext_pairs[i].extension;
161  found_match = true;
162  }
163  }
164  if (!found_match)
165  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
166  std::string glob(dir_ext_pairs[i].image_dir);
167  glob += "/*";
168  vul_file_iterator fn(glob);
169  for (;!found_match && bool(fn);++fn)
170  if (filter_dirent(fn(), dir_ext_pairs[i].extension)) {
171  image_dir_ = dir_ext_pairs[i].image_dir;
172  image_extension_ = dir_ext_pairs[i].extension;
173  found_match = true;
174  }
175  }
176  if (!found_match) {
177  std::cerr << __FILE__ << " : Can't find files matching " << basename_
178  << index_format_ << " in common locations with common format!\n";
179  std::abort();
180  }
181  }
182 
183  // Only image dir is blank :
184  // 1 - Look for basename-compatible files in cwd
185  // 2 - Look for basename-compatible files in dir corresponding to given image extension
186  // 3 - Look for basename-compatible files in common image dirs
187  else if (image_dir_ == "")
188  {
189  bool found_match = false;
190  {
191  for (vul_file_iterator fn("./*"); !found_match && bool(fn); ++fn)
192  if (filter_dirent(fn.filename(), image_extension_)) {
193  image_dir_ = "./";
194  found_match = true;
195  }
196  }
197 
198  if (!found_match) {
199  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
200  if (std::string(dir_ext_pairs[i].extension) == image_extension_) {
201  std::string glob(dir_ext_pairs[i].image_dir); glob += "*";
202  for (vul_file_iterator fn(glob); !found_match && bool(fn); ++fn)
203  if (filter_dirent(fn.filename(), image_extension_)) {
204  image_dir_ = dir_ext_pairs[i].image_dir;
205  found_match = true;
206  }
207  }
208  }
209 
210  if (!found_match) {
211  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
212  std::string glob(dir_ext_pairs[i].image_dir); glob += "*";
213  for (vul_file_iterator fn(glob); !found_match && bool(fn); ++fn)
214  if (filter_dirent(fn.filename(), image_extension_)) {
215  image_dir_ = dir_ext_pairs[i].image_dir;
216  found_match = true;
217  }
218  }
219  }
220 
221  if (!found_match) {
222  std::cerr << __FILE__ << " : Can't find files matching " << basename_
223  << index_format_<<image_extension_ << " in common locations!\n";
224  std::abort();
225  }
226  }
227 
228  // Only extension is blank :
229  // 1 - Look in image dir for basename-compatible files with extension corresponding to the image dir
230  // 2 - Look in image dir for basename-compatible files with common image extensions
231  else if (image_extension_ == "")
232  {
233  bool found_match = false;
234  {
235  std::string glob(image_dir_ + "*");
236  vul_file_iterator fn(glob);
237  if (fn) {
238  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i)
239  if (std::string(dir_ext_pairs[i].image_dir) == image_dir_) {
240  for (;!found_match && bool(fn);++fn)
241  if (filter_dirent(fn.filename(), dir_ext_pairs[i].extension)) {
242  image_extension_ = dir_ext_pairs[i].extension;
243  found_match = true;
244  }
245  }
246  }
247  }
248 
249  if (!found_match) {
251  if (fn) {
252  for (int i=0; i < num_dir_ext_pairs && !found_match; ++i) {
253  for (;!found_match && bool(fn); ++fn)
254  if (filter_dirent(fn.filename(), dir_ext_pairs[i].extension)) {
255  image_extension_ = dir_ext_pairs[i].extension;
256  found_match = true;
257  }
258  }
259  }
260  }
261 
262  if (!found_match) {
263  std::cerr << __FILE__ << " : Can't find files matching " << image_dir_
264  << basename_ << index_format_ << " with common extension!\n";
265  std::abort();
266  }
267  }
268 
269  // Start and/or end is not specified :
270  // Find all basename-compatible files and set sequence indices accordingly
271  if (indices_.size() == 0)
272  {
273  // See if we need to scan the image directory to get the sequence start/end
274  if (start_ == -1 || end_ == -1) {
275  int max = -1000000;
276  int min = 1000000;
277  for (vul_file_iterator fn(image_dir_ + "*");fn;++fn)
278  if (filter_dirent(fn.filename(), image_extension_)) {
279  int index = extract_index(fn.filename());
280  max = (index > max) ? index : max;
281  min = (index < min) ? index : min;
282  }
283  if (max < min) {
284  std::cerr << "vul_sequence_filename_map: WARNING: no files in " << image_dir_ << std::endl;
285  }
286 
287  if (start_ == -1) start_ = min;
288  if (end_ == -1) end_ = max;
289  }
290  for (int i=start_; i <= end_; i = i+step_)
291  indices_.push_back(i);
292  }
293 
294  if (debug)
295  std::cerr << seq_template_ << std::endl
296  << " image dir : " << image_dir_ << std::endl
297  << " basename : " << basename_ << std::endl
298  << " index format : " << index_format_ << std::endl
299  << " extension : " << image_extension_ << std::endl
300  << " indices : " << start_ << ':' << step_ << ':' << end_
301  << std::endl << std::endl;
302 }
303 
305 {
306  int idx = -1;
307  for (int i=0; i < int(indices_.size()); ++i)
308  if (indices_[i] == real) {
309  idx = i;
310  break;
311  }
312  return idx;
313 }
314 
315 
316 std::ostream& vul_sequence_filename_map::print (std::ostream& s) const
317 {
318  s << "vul_sequence_filename_map : " << image_dir_ << basename_
319  << index_format_ << image_extension_ << " [" << indices_[0] << ':'
320  << indices_[1] - indices_[0] << ':' << indices_.back() << "]\n";
321 
322 #if 0
323  s << vul_sprintf("vul_sequence_filename_map : %s%s%s [%i:%i:%i]",
324  image_dir_.c_str(), basename_.c_str(), index_format_.c_str(), image_extension_.c_str(),
325  indices_[0], indices_[1] - indices_[0], indices_.back());
326 #endif
327  return s;
328 }
329 
330 bool vul_sequence_filename_map::filter_dirent(char const* name_string, std::string const& extension)
331 {
332  static std::size_t expected_length = 0L;
333  if (expected_length == 0L)
334  expected_length = basename_.size() +
335  (std::string(vul_sprintf(index_format_.c_str(),0)) + extension).size();
336 
337  std::string name_str(name_string);
338 
339  return name_str.size() == expected_length
340  && name_str.substr(0,basename_.size()) == basename_
341  && name_str.substr(expected_length-extension.size(), std::string::npos) == extension;
342 }
343 
344 int vul_sequence_filename_map::extract_index(char const* name_string)
345 {
346  std::string name_str(name_string);
347  std::string index_str = name_str.substr(basename_.size(), name_str.size() - image_extension_.size());
348  return std::atoi(index_str.c_str());
349 }
350 
351 std::ostream& operator<<(std::ostream &os, const vul_sequence_filename_map& s)
352 {
353  return s.print(os);
354 }
std::ostream & print(std::ostream &s) const
pretty print.
char const * image_dir
Pattern matching with regular expressions.
Definition: vul_reg_exp.h:82
char const * extension
Contains class for mapping sequence frame indices to filenames.
bool find(char const *)
true if regexp in char* arg.
char const * filename()
Return the non-directory part of the current pathname.
int get_mapped_index(int real) const
returns the frame number corresp. to on-disk index N, or -1 if out-of-range.
class to iterate through directories and/or "glob" patterns (*.
std::ostream & operator<<(std::ostream &os, const vul_sequence_filename_map &s)
constexpr bool debug
std::string name(int frame)
returns frame name with no extension, e.g. "img.003", "img.003.004".
std::string triplet_name(int i, int j, int k)
Iterate through directories and/or "glob" patterns (*.
const int num_dir_ext_pairs
bool filter_dirent(char const *name, std::string const &extension)
contains class for pattern matching with regular expressions
std::ptrdiff_t start() const
Returns the start index of the last item found.
Definition: vul_reg_exp.h:115
Maps sequence frame indices to filenames.
C++ conforming replacement to the ANSI C functions sprintf and printf.
Definition: vul_sprintf.h:31
std::string match(int n) const
Return nth submatch as a string.
Definition: vul_reg_exp.h:136
std::string pair_name(int i, int j)
creates a formatted ANSI C++ string