Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
pto_lensstack.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This software is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public
22  * License along with this software. If not, see
23  * <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #include <fstream>
28 #include <sstream>
29 #include <getopt.h>
30 #include <panodata/Panorama.h>
32 #include "hugin_utils/utils.h"
33 
34 struct ParsedImg
35 {
36  int imgNr;
38  ParsedImg(): imgNr(-1), lensStackNr(-1) {};
39 };
40 
41 typedef std::vector<ParsedImg> ParseImgVec;
42 
43 // parse a single variable and put result in struct ParseVar
44 void ParseSingleImage(ParseImgVec& varVec, const std::string& s)
45 {
46  std::string text(s);
47  if (text[0] == 'i')
48  {
49  text.erase(0, 1);
50  ParsedImg var;
51  // search =
52  const std::size_t pos = text.find_first_of("=", 0);
53  if (pos == std::string::npos)
54  {
55  // no =, try to convert to number
56  if (!hugin_utils::stringToInt(text, var.imgNr))
57  {
58  return;
59  }
60  }
61  else
62  {
63  if (pos > 0 && pos < text.length() - 1)
64  {
65  std::string tempString(text.substr(0, pos));
66  if (!hugin_utils::stringToInt(tempString, var.imgNr))
67  {
68  return;
69  };
70  tempString = text.substr(pos + 1, text.length() - pos - 1);
71  if(!hugin_utils::stringToInt(tempString, var.lensStackNr))
72  {
73  return;
74  };
75  }
76  else
77  {
78  // = at first or last position of string
79  return;
80  };
81  };
82  varVec.push_back(var);
83  };
84 };
85 
86 //parse complete variables string
87 void ParseImageLensStackString(ParseImgVec& parseVec, std::string input)
88 {
89  std::vector<std::string> splitResult = hugin_utils::SplitString(input, ", ");
90  for(size_t i=0; i<splitResult.size(); i++)
91  {
92  ParseSingleImage(parseVec, splitResult[i]);
93  };
94 };
95 
96 // assign a new lens/stack
97 void NewPart(HuginBase::Panorama& pano, std::set<HuginBase::ImageVariableGroup::ImageVariableEnum> vars, unsigned int imgNr)
98 {
99  for (std::set<HuginBase::ImageVariableGroup::ImageVariableEnum>::iterator it = vars.begin(); it != vars.end(); ++it)
100  {
101  switch (*it)
102  {
103 #define image_variable( name, type, default_value )\
104 case HuginBase::ImageVariableGroup::IVE_##name:\
105  pano.unlinkImageVariable##name(imgNr);\
106  break;
108 #undef image_variable
109  }
110  }
111 };
112 
113 static void usage(const char* name)
114 {
115  std::cout << name << ": modify assigned lenses and stack in pto files" << std::endl
116  << name << " version " << hugin_utils::GetHuginVersion() << std::endl
117  << std::endl
118  << "Usage: " << name << " [options] --switches imglist input.pto" << std::endl
119  << std::endl
120  << " -o, --output=file.pto Output Hugin PTO file. Default: <filename>_lens.pto" << std::endl
121  << " -h, --help Shows this help" << std::endl
122  << std::endl
123  << " --new-lens imglist Assign to given images a new lens number" << std::endl
124  << " --new-stack imglist Assign to given images a new stack number" << std::endl
125  << " Examples:" << std::endl
126  << " --new-lens i2 Image 2 gets a new lens" << std::endl
127  << " --new-stack i4,i5 Images 4 and 5 get a new stack" << std::endl
128  << std::endl
129  << " --change-lens imglist Assign to given images a new lens number" << std::endl
130  << " --change-stack imglist Assign to given images a new stack number" << std::endl
131  << " Examples:" << std::endl
132  << " --change-lens i2=0 Image 2 is assigned lens number 0" << std::endl
133  << " --change-stack i4=0,i5=1 Image 4 is assigned to stack 0," << std::endl
134  << " image 5 to stack number 1" << std::endl
135  << std::endl;
136 }
137 
138 int main(int argc, char* argv[])
139 {
140  // parse arguments
141  const char* optstring = "o:h";
142 
143  enum
144  {
145  SWITCH_NEW_LENS=1000,
146  SWITCH_NEW_STACK,
147  SWITCH_CHANGE_LENS,
148  SWITCH_CHANGE_STACK
149  };
150  static struct option longOptions[] =
151  {
152  {"output", required_argument, NULL, 'o' },
153  {"new-lens", required_argument, NULL, SWITCH_NEW_LENS },
154  {"new-stack", required_argument, NULL, SWITCH_NEW_STACK },
155  {"change-lens", required_argument, NULL, SWITCH_CHANGE_LENS },
156  {"change-stack", required_argument, NULL, SWITCH_CHANGE_STACK },
157  {"help", no_argument, NULL, 'h' },
158  0
159  };
160 
161  ParseImgVec newLensImgs;
162  ParseImgVec newStackImgs;
163  ParseImgVec changeLensImgs;
164  ParseImgVec changeStackImgs;
165  int c;
166  std::string output;
167  while ((c = getopt_long (argc, argv, optstring, longOptions,nullptr)) != -1)
168  {
169  switch (c)
170  {
171  case 'o':
172  output = optarg;
173  break;
174  case 'h':
175  usage(hugin_utils::stripPath(argv[0]).c_str());
176  return 0;
177  case SWITCH_NEW_LENS:
178  ParseImageLensStackString(newLensImgs, std::string(optarg));
179  break;
180  case SWITCH_NEW_STACK:
181  ParseImageLensStackString(newStackImgs, std::string(optarg));
182  break;
183  case SWITCH_CHANGE_LENS:
184  ParseImageLensStackString(changeLensImgs, std::string(optarg));
185  break;
186  case SWITCH_CHANGE_STACK:
187  ParseImageLensStackString(changeStackImgs, std::string(optarg));
188  break;
189  case ':':
190  case '?':
191  // missing argument or invalid switch
192  return 1;
193  break;
194  default:
195  // this should not happen
196  abort();
197  }
198  }
199 
200  if (argc - optind != 1)
201  {
202  if (argc - optind < 1)
203  {
204  std::cerr << hugin_utils::stripPath(argv[0]) << ": No project file given." << std::endl;
205  }
206  else
207  {
208  std::cerr << hugin_utils::stripPath(argv[0]) << ": Only one project file expected." << std::endl;
209  };
210  return 1;
211  };
212 
213  if(newLensImgs.size() + newStackImgs.size() + changeLensImgs.size() + changeStackImgs.size()==0)
214  {
215  std::cerr << hugin_utils::stripPath(argv[0]) << ": no images/lens/stacks to modify given" << std::endl;
216  return 1;
217  };
218 
219  std::string input=argv[optind];
220  // read panorama
221  HuginBase::Panorama pano;
222  if (!pano.ReadPTOFile(input, hugin_utils::getPathPrefix(input)))
223  {
224  return 1;
225  };
226 
227  // new lenses
228  if(!newLensImgs.empty())
229  {
230  HuginBase::StandardImageVariableGroups variable_groups(pano);
231  if(variable_groups.getLenses().getNumberOfParts()<pano.getNrOfImages())
232  {
233  for(size_t i=0; i<newLensImgs.size(); i++)
234  {
235  //skip invalid image numbers
236  if(newLensImgs[i].imgNr<0 || newLensImgs[i].imgNr>=(int)pano.getNrOfImages())
237  {
238  continue;
239  };
240  std::cout << "Assigning a new lens to image " << newLensImgs[i].imgNr << std::endl;
241  NewPart(pano, HuginBase::StandardImageVariableGroups::getLensVariables(), newLensImgs[i].imgNr);
242  };
243  }
244  else
245  {
246  std::cout << "Warning: Pto project contains already for each image an own lens" << std::endl
247  << " Nothing to do." << std::endl;
248  };
249  std::cout << std::endl;
250  };
251 
252  // new stacks
253  if(!newStackImgs.empty())
254  {
255  HuginBase::StandardImageVariableGroups variable_groups(pano);
256  if(variable_groups.getStacks().getNumberOfParts()<pano.getNrOfImages())
257  {
258  for(size_t i=0; i<newStackImgs.size(); i++)
259  {
260  //skip invalid image numbers
261  if(newStackImgs[i].imgNr<0 || newStackImgs[i].imgNr>=(int)pano.getNrOfImages())
262  {
263  continue;
264  };
265  std::cout << "Assigning a new stack to image " << newStackImgs[i].imgNr << std::endl;
266  NewPart(pano, HuginBase::StandardImageVariableGroups::getStackVariables(), newStackImgs[i].imgNr);
267  };
268  }
269  else
270  {
271  std::cout << "Warning: Pto project contains already for each image an own stack" << std::endl
272  << " Nothing to do." << std::endl;
273  };
274  std::cout << std::endl;
275  };
276 
277  // change lenses
278  if(!changeLensImgs.empty())
279  {
280  HuginBase::StandardImageVariableGroups variable_groups(pano);
281  size_t lensCount=variable_groups.getLenses().getNumberOfParts();
282  if(lensCount>1)
283  {
284  for(size_t i=0; i<changeLensImgs.size(); i++)
285  {
286  //skip invalid image numbers
287  if(changeLensImgs[i].imgNr<0 || changeLensImgs[i].imgNr>=(int)pano.getNrOfImages())
288  {
289  continue;
290  };
291  if(changeLensImgs[i].lensStackNr<0 || changeLensImgs[i].lensStackNr>=lensCount)
292  {
293  continue;
294  };
296  if (pano.getImage(changeLensImgs[i].imgNr).getSize() == pano.getImage(*group.getPartsSet()[changeLensImgs[i].lensStackNr].begin()).getSize())
297  {
298  // check that image size are the same
299  std::cout << "Assigning image " << changeLensImgs[i].imgNr << " to lens " << changeLensImgs[i].lensStackNr << std::endl;
300  group.switchParts(changeLensImgs[i].imgNr, changeLensImgs[i].lensStackNr);
301  }
302  else
303  {
304  std::cout << "Warning: Image size of image " << changeLensImgs[i].imgNr << " is " << pano.getImage(changeLensImgs[i].imgNr).getSize() << std::endl
305  << " while images of lens " << changeLensImgs[i].lensStackNr << " have a size of " << pano.getImage(*group.getPartsSet()[changeLensImgs[i].lensStackNr].begin()).getSize() << "." << std::endl
306  << " All images of the same lens must have the same size." << std::endl
307  << " So skipping this image." << std::endl;
308  };
309  };
310  }
311  else
312  {
313  std::cout << "Warning: Pto project contains only one lens." << std::endl
314  << " Therefore the lens can not be changed. Use --new-lens instead." << std::endl;
315  };
316  std::cout << std::endl;
317  };
318 
319  // change stacks
320  if(!changeStackImgs.empty())
321  {
322  HuginBase::StandardImageVariableGroups variable_groups(pano);
323  size_t stackCount=variable_groups.getStacks().getNumberOfParts();
324  if(stackCount>1)
325  {
326  for(size_t i=0; i<changeStackImgs.size(); i++)
327  {
328  //skip invalid image numbers
329  if(changeStackImgs[i].imgNr<0 || changeStackImgs[i].imgNr>=(int)pano.getNrOfImages())
330  {
331  continue;
332  };
333  if(changeStackImgs[i].lensStackNr<0 || changeStackImgs[i].lensStackNr>=stackCount)
334  {
335  continue;
336  };
338  if (pano.getImage(changeStackImgs[i].imgNr).getSize() == pano.getImage(*group.getPartsSet()[changeStackImgs[i].lensStackNr].begin()).getSize())
339  {
340  // check that image size are the same
341  std::cout << "Assigning image " << changeStackImgs[i].imgNr << " to stack " << changeStackImgs[i].lensStackNr << std::endl;
342  group.switchParts(changeStackImgs[i].imgNr, changeStackImgs[i].lensStackNr);
343  }
344  else
345  {
346  std::cout << "Warning: Image size of image " << changeStackImgs[i].imgNr << " is " << pano.getImage(changeStackImgs[i].imgNr).getSize() << std::endl
347  << " while images of stack " << changeStackImgs[i].lensStackNr << " have a size of " << pano.getImage(*group.getPartsSet()[changeStackImgs[i].lensStackNr].begin()).getSize() << "." << std::endl
348  << " All images of the same stack must have the same size." << std::endl
349  << " So skipping this image." << std::endl;
350  };
351  };
352  }
353  else
354  {
355  std::cout << "Warning: Pto project contains only one stack." << std::endl
356  << " Therefore the stack can not be changed. Use --new-stack instead." << std::endl;
357  };
358  std::cout << std::endl;
359  };
360 
361  //write output
362  // Set output .pto filename if not given
363  output = hugin_utils::GetOutputFilename(output, input, "lens");
364  if (pano.WritePTOFile(output, hugin_utils::getPathPrefix(output)))
365  {
366  std::cout << std::endl << "Written project file " << output << std::endl;
367  };
368 
369  return 0;
370 }
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getLensVariables()
Get the set of lens image variables.
std::string GetOutputFilename(const std::string &out, const std::string &in, const std::string &suffix)
construct output filename, if ouput is known return this value otherwise use the input filename and a...
Definition: utils.cpp:420
ImageVariableGroup & getStacks()
Get the ImageVariableGroup representing the group of stack variables.
Somewhere to specify what variables belong to what.
options getSize().area()) int wxCALLBACK SortFieldOfViewAscending(wxIntPtr item1
Model for a panorama.
Definition: Panorama.h:152
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
bool ReadPTOFile(const std::string &filename, const std::string &prefix="")
read pto file from the given filename into Panorama object it does some checks on the file and issues...
Definition: Panorama.cpp:2023
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
bool stringToInt(const std::string &s, int &val)
convert string to integer value, returns true, if sucessful
Definition: utils.cpp:264
Same as above, but use a non const panorama.
static void usage()
Definition: Main.cpp:32
std::string GetHuginVersion()
return a string with version numbers
Definition: utils.cpp:920
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
std::vector< std::string > SplitString(const std::string &s, const std::string &sep)
split string s at given sep, returns vector of strings
Definition: utils.cpp:294
std::size_t getNumberOfParts() const
get the number of parts.
void switchParts(unsigned int ImageNr, unsigned int partNr)
switch a given image to a different part number.
This file specifies what image variables SrcPanoImg should have.
void ParseImageLensStackString(ParseImgVec &parseVec, std::string input)
std::vector< ParsedImg > ParseImgVec
static const std::set< ConstImageVariableGroup::ImageVariableEnum > & getStackVariables()
Get the set of stack image variables.
std::string stripPath(const std::string &filename)
remove the path of a filename (mainly useful for gui display of filenames)
Definition: utils.cpp:160
void ParseSingleImage(ParseImgVec &varVec, const std::string &s)
int main(int argc, char *argv[])
Definition: Main.cpp:167