Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FindPanoDialog.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
11 /* This 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  * Lesser 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 "FindPanoDialog.h"
28 #include "base_wx/wxPlatform.h"
29 #include "panoinc.h"
31 #include "PTBatcherGUI.h"
32 #include "hugin_utils/alphanum.h"
33 #include "hugin/config_defaults.h"
34 #include "wx/mstream.h"
35 #ifdef _WIN32
36 // workaround for a conflict between exiv2 and wxWidgets/CMake built
37 #define HAVE_PID_T 1
38 #endif
39 #include <exiv2/exiv2.hpp>
40 #ifdef _WIN32
41 #include <commctrl.h>
42 #endif
43 #include "base_wx/LensTools.h"
45 
46 enum
47 {
48  ID_REMOVE_IMAGE = wxID_HIGHEST + 300,
49  ID_SPLIT_PANOS = wxID_HIGHEST + 301
50 };
51 
52 BEGIN_EVENT_TABLE(FindPanoDialog,wxDialog)
53  EVT_BUTTON(XRCID("find_pano_close"), FindPanoDialog::OnButtonClose)
54  EVT_BUTTON(XRCID("find_pano_select_dir"), FindPanoDialog::OnButtonChoose)
55  EVT_BUTTON(XRCID("find_pano_start_stop"), FindPanoDialog::OnButtonStart)
56  EVT_BUTTON(XRCID("find_pano_add_queue"), FindPanoDialog::OnButtonSend)
57  EVT_LISTBOX(XRCID("find_pano_list"), FindPanoDialog::OnSelectPossiblePano)
58  EVT_LIST_ITEM_RIGHT_CLICK(XRCID("find_pano_selected_thumbslist"), FindPanoDialog::OnListItemRightClick)
59  EVT_MENU(ID_REMOVE_IMAGE, FindPanoDialog::OnRemoveImage)
60  EVT_MENU(ID_SPLIT_PANOS, FindPanoDialog::OnSplitPanos)
61  EVT_CLOSE(FindPanoDialog::OnClose)
63 
64 bool SortFilename::operator()(const HuginBase::SrcPanoImage* img1, const HuginBase::SrcPanoImage* img2) const
65 {
66  return doj::alphanum_comp(img1->getFilename(),img2->getFilename())<0;
67 };
68 
69 // thumbnail size currently set to 80x80
70 #define THUMBSIZE 80
71 
72 FindPanoDialog::FindPanoDialog(BatchFrame* batchframe, wxString xrcPrefix)
73 {
74  // load our children. some children might need special
75  // initialization. this will be done later.
76  wxXmlResource::Get()->LoadDialog(this,batchframe,wxT("find_pano_dialog"));
77 
78 #ifdef __WXMSW__
79  wxIconBundle myIcons(xrcPrefix+ wxT("data/ptbatcher.ico"),wxBITMAP_TYPE_ICO);
80  SetIcons(myIcons);
81 #else
82  wxIcon myIcon(xrcPrefix + wxT("data/ptbatcher.png"),wxBITMAP_TYPE_PNG);
83  SetIcon(myIcon);
84 #endif
85  m_batchframe=batchframe;
86  m_isRunning=false;
87  m_stopped=false;
88 
89  m_button_start=XRCCTRL(*this,"find_pano_start_stop",wxButton);
90  m_button_choose=XRCCTRL(*this,"find_pano_select_dir",wxButton);
91  m_button_send=XRCCTRL(*this,"find_pano_add_queue",wxButton);
92  m_button_close=XRCCTRL(*this,"find_pano_close",wxButton);
93  m_textctrl_dir=XRCCTRL(*this,"find_pano_dir",wxTextCtrl);
94  m_textctrl_dir->AutoCompleteDirectories();
95  m_cb_subdir=XRCCTRL(*this,"find_pano_subdir",wxCheckBox);
96  m_statustext=XRCCTRL(*this,"find_pano_label",wxStaticText);
97  m_list_pano=XRCCTRL(*this,"find_pano_list",wxCheckListBox);
98  m_ch_naming=XRCCTRL(*this,"find_pano_naming",wxChoice);
99  m_cb_createLinks=XRCCTRL(*this,"find_pano_create_links",wxCheckBox);
100  m_cb_loadDistortion=XRCCTRL(*this,"find_pano_load_distortion",wxCheckBox);
101  m_cb_loadVignetting=XRCCTRL(*this,"find_pano_load_vignetting",wxCheckBox);
102  m_sc_minNumberImages=XRCCTRL(*this, "find_pano_min_number_images", wxSpinCtrl);
103  m_sc_maxTimeDiff=XRCCTRL(*this, "find_pano_max_time_diff", wxSpinCtrl);
104  m_ch_blender = XRCCTRL(*this, "find_pano_default_blender", wxChoice);
106 
107  //set parameters
108  wxConfigBase* config = wxConfigBase::Get();
109  // restore position and size
110  int dx,dy;
111  wxDisplaySize(&dx,&dy);
112  bool maximized = config->Read(wxT("/FindPanoDialog/maximized"), 0l) != 0;
113  if (maximized)
114  {
115  this->Maximize();
116  }
117  else
118  {
119  //size
120  int w = config->Read(wxT("/FindPanoDialog/width"),-1l);
121  int h = config->Read(wxT("/FindPanoDialog/height"),-1l);
122  if (w > 0 && w <= dx)
123  {
124  this->SetClientSize(w,h);
125  }
126  else
127  {
128  this->Fit();
129  }
130  //position
131  int x = config->Read(wxT("/FindPanoDialog/positionX"),-1l);
132  int y = config->Read(wxT("/FindPanoDialog/positionY"),-1l);
133  if ( y >= 0 && x >= 0 && x < dx && y < dy)
134  {
135  this->Move(x, y);
136  }
137  else
138  {
139  this->Move(0, 44);
140  }
141  }
142  long splitterPos = config->Read(wxT("/FindPanoDialog/splitterPos"), -1l);
143  if (splitterPos != -1)
144  {
145  XRCCTRL(*this, "find_pano_splitter", wxSplitterWindow)->SetSashPosition(splitterPos);
146  };
147  wxString path=config->Read(wxT("/FindPanoDialog/actualPath"),wxEmptyString);
148  if(!path.IsEmpty())
149  {
150  m_textctrl_dir->SetValue(path);
151  }
152  bool val;
153  config->Read(wxT("/FindPanoDialog/includeSubDirs"),&val,false);
154  m_cb_subdir->SetValue(val);
155  long i=config->Read(wxT("/FindPanoDialog/Naming"),0l);
156  m_ch_naming->SetSelection(i);
157  config->Read(wxT("/FindPanoDialog/linkStacks"),&val,true);
158  m_cb_createLinks->SetValue(val);
159  config->Read(wxT("/FindPanoDialog/loadDistortion"),&val,false);
160  m_cb_loadDistortion->SetValue(val);
161  config->Read(wxT("/FindPanoDialog/loadVignetting"),&val,false);
162  m_cb_loadVignetting->SetValue(val);
163  i=config->Read(wxT("/FindPanoDialog/MinNumberImages"), 2l);
164  m_sc_minNumberImages->SetValue(i);
165  i=config->Read(wxT("/FindPanoDialog/MaxTimeDiff"), 30l);
166  m_sc_maxTimeDiff->SetValue(i);
167  i = config->Read(wxT("/FindPanoDialog/DefaultBlender"), static_cast<long>(HuginBase::PanoramaOptions::ENBLEND_BLEND));
169  m_button_send->Disable();
170  m_thumbs = new wxImageList(THUMBSIZE, THUMBSIZE, true, 0);
171  m_thumbsList = XRCCTRL(*this, "find_pano_selected_thumbslist", wxListCtrl);
172  m_thumbsList->SetImageList(m_thumbs, wxIMAGE_LIST_NORMAL);
173  m_thumbsList->Bind(wxEVT_MOTION, &FindPanoDialog::OnListMouseMove, this);
174 #ifdef _WIN32
175  // default image spacing is too big, wxWidgets does not provide direct
176  // access to the spacing, so using the direct API function
177  ListView_SetIconSpacing(m_thumbsList->GetHandle(), THUMBSIZE + 20, THUMBSIZE + 20);
178 #endif
179 };
180 
182 {
183  wxConfigBase* config=wxConfigBase::Get();
184  if(!this->IsMaximized())
185  {
186  wxSize sz = this->GetClientSize();
187  config->Write(wxT("/FindPanoDialog/width"), sz.GetWidth());
188  config->Write(wxT("/FindPanoDialog/height"), sz.GetHeight());
189  wxPoint ps = this->GetPosition();
190  config->Write(wxT("/FindPanoDialog/positionX"), ps.x);
191  config->Write(wxT("/FindPanoDialog/positionY"), ps.y);
192  config->Write(wxT("/FindPanoDialog/maximized"), 0);
193  }
194  else
195  {
196  config->Write(wxT("/FindPanoDialog/maximized"), 1l);
197  };
198  config->Write(wxT("/FindPanoDialog/splitterPos"), XRCCTRL(*this, "find_pano_splitter", wxSplitterWindow)->GetSashPosition());
199  config->Write(wxT("/FindPanoDialog/actualPath"),m_textctrl_dir->GetValue());
200  config->Write(wxT("/FindPanoDialog/includeSubDirs"),m_cb_subdir->GetValue());
201  config->Write(wxT("/FindPanoDialog/Naming"),m_ch_naming->GetSelection());
202  config->Write(wxT("/FindPanoDialog/linkStacks"),m_cb_createLinks->GetValue());
203  config->Write(wxT("/FindPanoDialog/loadDistortion"),m_cb_loadDistortion->GetValue());
204  config->Write(wxT("/FindPanoDialog/loadVignetting"),m_cb_loadDistortion->GetValue());
205  config->Write(wxT("/FindPanoDialog/MinNumberImages"), m_sc_minNumberImages->GetValue());
206  config->Write(wxT("/FindPanoDialog/MaxTimeDiff"), m_sc_maxTimeDiff->GetValue());
207  config->Write(wxT("/FindPanoDialog/DefaultBlender"), static_cast<long>(GetSelectedValue(m_ch_blender)));
208  CleanUpPanolist();
209  delete m_thumbs;
210 };
211 
213 {
214  while(!m_panos.empty())
215  {
216  delete m_panos.back();
217  m_panos.pop_back();
218  };
219 };
220 
221 //prevent closing window when running detection
222 void FindPanoDialog::OnClose(wxCloseEvent& e)
223 {
224  if(e.CanVeto() && m_isRunning)
225  {
226  wxBell();
227  e.Veto();
228  }
229  else
230  {
231  e.Skip();
232  };
233 };
234 
235 void FindPanoDialog::OnButtonClose(wxCommandEvent& e)
236 {
237  if(!m_panos.empty())
238  {
239  if(wxMessageBox(_("The list contains possibly unprocessed panoramas.\nIf you close the dialog, you will lose them.\nContinue anyway?"),
240  _("Question"),wxYES_NO|wxICON_WARNING,this)==wxNO)
241  {
242  return;
243  };
244  };
245  this->Close();
246 };
247 
248 void FindPanoDialog::OnButtonChoose(wxCommandEvent& e)
249 {
250  wxDirDialog dlg(this, _("Specify a directory to search for projects in"),
251  m_textctrl_dir->GetValue(), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST);
252  if (dlg.ShowModal()==wxID_OK)
253  {
254  m_textctrl_dir->SetValue(dlg.GetPath());
255  };
256 };
257 
258 void FindPanoDialog::OnButtonStart(wxCommandEvent& e)
259 {
260  if(m_isRunning)
261  {
262  //stop detection
263  m_stopped=true;
264  m_button_start->SetLabel(_("Accepted"));
265  }
266  else
267  {
268  //start detection
269  m_start_dir=m_textctrl_dir->GetValue();
270  if(wxDir::Exists(m_start_dir))
271  {
272  if(!m_panos.empty())
273  {
274  if (wxMessageBox(_("The list contains still not yet processed panoramas.\nIf you continue, they will be disregarded.\nDo you still want to continue?"),
275  _("Question"),wxYES_NO|wxICON_WARNING,this)==wxNO)
276  {
277  return;
278  };
279  };
280  m_isRunning=true;
281  m_stopped=false;
282  //deactivate TIFF warning message boxes
283  m_oldtiffwarning=TIFFSetWarningHandler(NULL);
284  m_button_start->SetLabel(_("Stop"));
285  CleanUpPanolist();
286  m_list_pano->Clear();
287  wxCommandEvent dummy;
288  OnSelectPossiblePano(dummy);
289  EnableButtons(false);
290  SearchInDir(m_start_dir,m_cb_subdir->GetValue(), m_cb_loadDistortion->GetValue(), m_cb_loadVignetting->GetValue(),
291  m_sc_minNumberImages->GetValue(), m_sc_maxTimeDiff->GetValue());
292  }
293  else
294  {
295  wxMessageBox(wxString::Format(_("Directory %s does not exist.\nPlease give an existing directory."),m_start_dir.c_str()),
296  _("Warning"),wxOK | wxICON_EXCLAMATION,this);
297  };
298  };
299 }
300 
301 void FindPanoDialog::OnButtonSend(wxCommandEvent& e)
302 {
303  if(m_panos.empty())
304  {
305  return;
306  }
307  unsigned int nr=0;
308  for(unsigned int i=0; i<m_list_pano->GetCount(); i++)
309  {
310  if(m_list_pano->IsChecked(i))
311  {
312  nr++;
313  };
314  };
315  if(nr==0)
316  {
317  wxMessageBox(_("You have selected no possible panorama.\nPlease select at least one panorama and try again."),_("Warning"),wxOK|wxICON_EXCLAMATION,this);
318  return;
319  }
320  bool failed=false;
321  bool createLinks=m_cb_createLinks->GetValue();
322  for(unsigned int i=0; i<m_list_pano->GetCount(); i++)
323  {
324  if(m_list_pano->IsChecked(i))
325  {
326  wxString filename=m_panos[i]->GeneratePanorama((PossiblePano::NamingConvention)(m_ch_naming->GetSelection()),createLinks,
327  static_cast<HuginBase::PanoramaOptions::BlendingMechanism>(GetSelectedValue(m_ch_blender)));
328  if(!filename.IsEmpty())
329  {
331  }
332  else
333  {
334  failed=true;
335  };
336  };
337  };
338  if(failed)
339  {
340  wxMessageBox(_("Not all project files could be written successfully.\nMaybe you have no write permission for these directories or your disc is full."),_("Error"),wxOK,this);
341  };
342  this->Close();
343 };
344 
345 void FindPanoDialog::EnableButtons(const bool state)
346 {
347  m_textctrl_dir->Enable(state);
348  m_button_choose->Enable(state);
349  m_cb_subdir->Enable(state);
350  m_ch_naming->Enable(state);
351  m_cb_createLinks->Enable(state);
352  m_button_close->Enable(state);
353  m_button_send->Enable(state);
354 };
355 
357 {
358  int selected = m_list_pano->GetSelection();
359  if (selected != wxNOT_FOUND)
360  {
361  XRCCTRL(*this, "find_pano_selected_cam", wxStaticText)->SetLabel(m_panos[selected]->GetCameraName());
362  XRCCTRL(*this, "find_pano_selected_lens", wxStaticText)->SetLabel(m_panos[selected]->GetLensName());
363  XRCCTRL(*this, "find_pano_selected_focallength", wxStaticText)->SetLabel(m_panos[selected]->GetFocalLength());
364  XRCCTRL(*this, "find_pano_selected_date_time", wxStaticText)->SetLabel(m_panos[selected]->GetStartString() + wxT(" (")+ m_panos[selected]->GetDuration() + wxT(")"));
365  m_panos[selected]->PopulateListCtrl(m_thumbsList, m_thumbs, m_tooltips);
366  }
367  else
368  {
369  XRCCTRL(*this, "find_pano_selected_cam", wxStaticText)->SetLabel(wxEmptyString);
370  XRCCTRL(*this, "find_pano_selected_lens", wxStaticText)->SetLabel(wxEmptyString);
371  XRCCTRL(*this, "find_pano_selected_focallength", wxStaticText)->SetLabel(wxEmptyString);
372  XRCCTRL(*this, "find_pano_selected_date_time", wxStaticText)->SetLabel(wxEmptyString);
373  m_thumbsList->DeleteAllItems();
374  m_thumbs->RemoveAll();
375  m_tooltips.Clear();
376  };
377 };
378 
380 {
381  // build menu
382  wxMenu contextMenu;
383  const int selectedPano = m_list_pano->GetSelection();
384  if (m_panos[selectedPano]->GetImageCount() > 2)
385  {
386  contextMenu.Append(ID_REMOVE_IMAGE, _("Remove image from project"));
387  };
388  long imageIndex = -1;
389  imageIndex = m_thumbsList->GetNextItem(imageIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
390  if(imageIndex > 1 && imageIndex <= static_cast<long>(m_panos[selectedPano]->GetImageCount()) - 2)
391  {
392  contextMenu.Append(ID_SPLIT_PANOS, _("Split here into two panoramas"));
393  }
394  // show popup menu
395  if (contextMenu.GetMenuItemCount() > 0)
396  {
397  PopupMenu(&contextMenu);
398  };
399 };
400 
401 void FindPanoDialog::OnRemoveImage(wxCommandEvent &e)
402 {
403  const int selectedPano = m_list_pano->GetSelection();
404  if (selectedPano != wxNOT_FOUND)
405  {
406  if (m_panos[selectedPano]->GetImageCount() > 2)
407  {
408  long imageIndex = -1;
409  imageIndex = m_thumbsList->GetNextItem(imageIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
410  if (imageIndex != wxNOT_FOUND)
411  {
412  // remove image from possible pano
413  m_panos[selectedPano]->RemoveImage(imageIndex);
414  // now remove from the wxListCtrl
415  m_thumbsList->DeleteItem(imageIndex);
416  // update the pano list
417  m_list_pano->SetString(selectedPano, m_panos[selectedPano]->GetItemString(m_start_dir));
418  // update the labels above
419  wxCommandEvent dummy;
420  OnSelectPossiblePano(dummy);
421  };
422  };
423  };
424 };
425 
426 void FindPanoDialog::OnSplitPanos(wxCommandEvent &e)
427 {
428  const int selectedPano = m_list_pano->GetSelection();
429  if (selectedPano != wxNOT_FOUND)
430  {
431  long imageIndex = -1;
432  imageIndex = m_thumbsList->GetNextItem(imageIndex, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
433  if (imageIndex != wxNOT_FOUND)
434  {
435  if (imageIndex > 1 && imageIndex <= static_cast<long>(m_panos[selectedPano]->GetImageCount()) - 2)
436  {
437  // do split
438  PossiblePano* newSubPano = m_panos[selectedPano]->SplitPano(imageIndex);
439  if (newSubPano->GetImageCount() > 0)
440  {
441  // insert new pano into internal list
442  m_panos.insert(m_panos.begin() + selectedPano + 1, newSubPano);
443  // update pano list
444  m_list_pano->SetString(selectedPano, m_panos[selectedPano]->GetItemString(m_start_dir));
445  int newItem = m_list_pano->Insert(m_panos[selectedPano + 1]->GetItemString(m_start_dir), selectedPano + 1);
446  m_list_pano->Check(newItem, true);
447  // update display
448  wxCommandEvent dummy;
449  OnSelectPossiblePano(dummy);
450  }
451  else
452  {
453  wxBell();
454  delete newSubPano;
455  };
456  };
457  };
458  };
459 }
460 
461 void FindPanoDialog::OnListMouseMove(wxMouseEvent & e)
462 {
463  if (m_tooltips.IsEmpty())
464  {
465  return;
466  }
467  int flags;
468  long item = m_thumbsList->HitTest(e.GetPosition(), flags);
469  if (item != wxNOT_FOUND && (flags&wxLIST_HITTEST_ONITEM) && item < m_tooltips.GetCount())
470  {
471  m_thumbsList->SetToolTip(m_tooltips[item]);
472  }
473  else
474  {
475  m_thumbsList->UnsetToolTip();
476  };
477 };
478 
479 int SortWxFilenames(const wxString& s1,const wxString& s2)
480 {
481  return doj::alphanum_comp(std::string(s1.mb_str(wxConvLocal)),std::string(s2.mb_str(wxConvLocal)));
482 };
483 
484 void FindPanoDialog::SearchInDir(wxString dirstring, const bool includeSubdir, const bool loadDistortion, const bool loadVignetting, const size_t minNumberImages, const size_t maxTimeDiff)
485 {
486  std::vector<PossiblePano*> newPanos;
487  wxTimeSpan max_diff(0, 0, maxTimeDiff, 0);
488  wxString filename;
489  wxArrayString fileList;
490  wxDir::GetAllFiles(dirstring,&fileList,wxEmptyString,wxDIR_FILES|wxDIR_HIDDEN);
491  fileList.Sort(SortWxFilenames);
492  //map for caching projection information to prevent reading from database for each image
493  for(size_t j=0; j<fileList.size() && !m_stopped; j++)
494  {
495  m_statustext->SetLabel(wxString::Format(_("Reading file %s"),fileList[j].c_str()));
496  wxFileName file(fileList[j]);
497  file.MakeAbsolute();
498  wxString ext=file.GetExt();
499  if(ext.CmpNoCase(wxT("jpg"))==0 || ext.CmpNoCase(wxT("jpeg"))==0 ||
500  ext.CmpNoCase(wxT("tif"))==0 || ext.CmpNoCase(wxT("tiff"))==0)
501  {
502  std::string filenamestr(file.GetFullPath().mb_str(HUGIN_CONV_FILENAME));
504  img->setFilename(filenamestr);
505  img->readEXIF();
506  // check for black/white images, if so skip
507  const HuginBase::FileMetaData& metadata = img->getFileMetadata();
508  HuginBase::FileMetaData::const_iterator it = metadata.find("pixeltype");
509  if (it != metadata.end())
510  {
511  if (it->second == "BILEVEL")
512  {
513  wxGetApp().Yield(true);
514  continue;
515  };
516  };
517  img->applyEXIFValues();
518  if(!img->getExifMake().empty() && !img->getExifModel().empty() &&
519  img->getExifFocalLength()!=0 && img->getCropFactor()!=0)
520  {
521  img->readProjectionFromDB(false);
522  if(loadDistortion)
523  {
524  img->readDistortionFromDB();
525  };
526  if(loadVignetting)
527  {
528  img->readVignettingFromDB();
529  };
530  bool found=false;
531  for(unsigned int i=0; i<newPanos.size() && !m_stopped && !found; i++)
532  {
533  //compare with all other image groups
534  if(newPanos[i]->BelongsTo(img,max_diff))
535  {
536  newPanos[i]->AddSrcPanoImage(img);
537  found=true;
538  };
539  if(i%10==0)
540  {
541  wxGetApp().Yield(true);
542  };
543  };
544  if(!found)
545  {
546  PossiblePano* newPano=new PossiblePano();
547  newPano->AddSrcPanoImage(img);
548  newPanos.push_back(newPano);
549  };
550  }
551  else
552  {
553  //could not read exif infos, disregard this image
554  delete img;
555  };
556  };
557  //allow processing events
558  wxGetApp().Yield(true);
559  };
560  if(!m_stopped && !newPanos.empty())
561  {
562  for(size_t i=0; i<newPanos.size(); i++)
563  {
564  if(newPanos[i]->GetImageCount()>=minNumberImages)
565  {
566  m_panos.push_back(newPanos[i]);
567  int newItem=m_list_pano->Append(m_panos[m_panos.size()-1]->GetItemString(m_start_dir));
568  m_list_pano->Check(newItem,true);
569  }
570  else
571  {
572  delete newPanos[i];
573  };
574  };
575  };
576 
577  if(includeSubdir && !m_stopped)
578  {
579  //now we go into all directories
580  wxDir dir(dirstring);
581  bool cont=dir.GetFirst(&filename,wxEmptyString,wxDIR_DIRS);
582  while(cont && !m_stopped)
583  {
584  SearchInDir(dir.GetName()+wxFileName::GetPathSeparator()+filename,includeSubdir, loadDistortion, loadVignetting, minNumberImages, maxTimeDiff);
585  cont=dir.GetNext(&filename);
586  }
587  };
588  if(m_start_dir.Cmp(dirstring)==0)
589  {
590  m_stopped=false;
591  m_isRunning=false;
592  m_button_start->SetLabel(_("Start"));
593  EnableButtons(true);
594  //enable send button if at least one panorama found
595  m_button_send->Enable(!m_panos.empty());
596  if(!m_panos.empty())
597  {
598  m_statustext->SetLabel(wxString::Format(_("Found %d possible panoramas"), static_cast<int>(m_panos.size())));
599  }
600  else
601  {
602  m_statustext->SetLabel(_("No possible panoramas found"));
603  };
604  TIFFSetWarningHandler(m_oldtiffwarning);
605  };
606 };
607 
609 {
610  if(!m_images.empty())
611  {
612  for(ImageSet::reverse_iterator it=m_images.rbegin(); it!=m_images.rend(); ++it)
613  {
614  delete (*it);
615  }
616  };
617 };
618 
619 bool PossiblePano::BelongsTo(HuginBase::SrcPanoImage* img, const wxTimeSpan max_time_diff)
620 {
621  if(m_make.compare(img->getExifMake())!=0)
622  {
623  return false;
624  }
625  if(m_camera.compare(img->getExifModel())!=0)
626  {
627  return false;
628  }
629  if(m_lens.compare(img->getExifLens())!=0)
630  {
631  return false;
632  }
633  if(fabs(m_focallength-img->getExifFocalLength())>0.01)
634  {
635  return false;
636  }
637  if (fabs(m_cropfactor - img->getCropFactor()) > 0.01)
638  {
639  return false;
640  }
641  if(m_size!=img->getSize())
642  {
643  return false;
644  }
645  if(!GetDateTime(img).IsBetween(m_dt_start-max_time_diff,m_dt_end+max_time_diff))
646  {
647  return false;
648  };
649  return true;
650 };
651 
653 {
654  struct tm exifdatetime;
655  if(img->getExifDateTime(&exifdatetime)==0)
656  {
657  return wxDateTime(exifdatetime);
658  }
659  else
660  {
661  wxFileName file(wxString(img->getFilename().c_str(),HUGIN_CONV_FILENAME));
662  return file.GetModificationTime();
663  };
664 };
665 
667 {
668  if(m_images.empty())
669  {
670  //fill all values from first image
671  m_make=img->getExifMake();
672  m_camera=img->getExifModel();
673  m_lens=img->getExifLens();
674  m_focallength=img->getExifFocalLength();
675  m_cropfactor = img->getCropFactor();
676  m_size=img->getSize();
677  m_dt_start=GetDateTime(img);
679  }
680  else
681  {
682  wxDateTime dt=GetDateTime(img);
683  if(dt.IsEarlierThan(m_dt_start))
684  {
685  m_dt_start=dt;
686  }
687  if(dt.IsLaterThan(m_dt_end))
688  {
689  m_dt_end=dt;
690  };
691  };
692  m_images.insert(img);
693 };
694 
695 const wxString PossiblePano::GetFilestring(const wxString BasePath, const bool stripExtension) const
696 {
697  ImageSet::const_iterator it=m_images.begin();
698  wxFileName f1(wxString((*it)->getFilename().c_str(),HUGIN_CONV_FILENAME));
699  f1.MakeRelativeTo(BasePath);
700  ImageSet::const_reverse_iterator rit=m_images.rbegin();
701  wxFileName f2(wxString((*rit)->getFilename().c_str(),HUGIN_CONV_FILENAME));
702  if(stripExtension)
703  {
704  return f1.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR)+f1.GetName()+wxT("-")+f2.GetName();
705  }
706  else
707  {
708  return f1.GetFullPath()+wxT(" - ")+f2.GetFullName();
709  };
710 };
711 
712 const wxString PossiblePano::GetItemString(const wxString BasePath) const
713 {
714  return wxString::Format(_("%d images: %s"), static_cast<int>(m_images.size()), GetFilestring(BasePath).c_str());
715 };
716 
717 bool PossiblePano::GetNewProjectFilename(NamingConvention nc,const wxString basePath, wxFileName& projectFile)
718 {
719  wxString mask;
720  unsigned int i=1;
721  projectFile.SetPath(basePath);
722  projectFile.SetName(wxT("pano"));
723  projectFile.SetExt(wxT("pto"));
724  if(!projectFile.IsDirWritable())
725  {
726  return false;
727  };
728  switch(nc)
729  {
730  case NAMING_PANO:
731  mask=wxT("panorama%d");
732  break;
733  case NAMING_FIRST_LAST:
734  mask=GetFilestring(basePath,true);
735  projectFile.SetName(mask);
736  if(!projectFile.FileExists())
737  {
738  return true;
739  };
740  mask=mask+wxT("_%d");
741  break;
742  case NAMING_FOLDER:
743  {
744  wxArrayString folders=projectFile.GetDirs();
745  if(folders.GetCount()==0)
746  {
747  return false;
748  }
749  mask=folders.Last();
750  projectFile.SetName(mask);
751  if(!projectFile.FileExists())
752  {
753  return true;
754  }
755  mask=mask+wxT("_%d");
756  }
757  break;
758  case NAMING_TEMPLATE:
759  {
760  HuginBase::Panorama tempPano;
761  tempPano.addImage(**m_images.begin());
762  tempPano.addImage(**m_images.rbegin());
763  wxFileName newProject(getDefaultProjectName(tempPano));
764  mask=newProject.GetName();
765  projectFile.SetName(mask);
766  if(!projectFile.FileExists())
767  {
768  return true;
769  }
770  mask=mask+wxT("_%d");
771  };
772  break;
773  default:
774  mask=wxT("panorama%d");
775  };
776 
777  projectFile.SetName(wxString::Format(mask,i));
778  while(projectFile.FileExists())
779  {
780  i++;
781  projectFile.SetName(wxString::Format(mask,i));
782  //security fall through
783  if(i>1000)
784  {
785  return false;
786  };
787  }
788  return true;
789 };
790 
792 {
793  if(m_images.empty())
794  {
795  return wxEmptyString;
796  };
797  ImageSet::const_iterator it=m_images.begin();
798  wxFileName firstFile(wxString((*it)->getFilename().c_str(),HUGIN_CONV_FILENAME));
799  firstFile.MakeAbsolute();
800  wxFileName projectFile;
801  if(!GetNewProjectFilename(nc,firstFile.GetPath(),projectFile))
802  {
803  return wxEmptyString;
804  };
805  //generate panorama
806  double redBalanceAnchor = (*m_images.begin())->getExifRedBalance();
807  double blueBalanceAnchor = (*m_images.begin())->getExifBlueBalance();
808  if (fabs(redBalanceAnchor)<1e-2)
809  {
810  redBalanceAnchor = 1;
811  };
812  if (fabs(blueBalanceAnchor)<1e-2)
813  {
814  blueBalanceAnchor = 1;
815  };
816  HuginBase::Panorama pano;
817  for(ImageSet::iterator it=m_images.begin(); it!=m_images.end(); ++it)
818  {
819  (*it)->setWhiteBalanceRed((*it)->getExifRedBalance() / redBalanceAnchor);
820  (*it)->setWhiteBalanceBlue((*it)->getExifBlueBalance() / blueBalanceAnchor);
821  pano.addImage(*(*it));
822  };
823  //assign all images the same lens number
824  HuginBase::StandardImageVariableGroups variable_groups(pano);
825  HuginBase::ImageVariableGroup& lenses = variable_groups.getLenses();
826  if(pano.getNrOfImages()>1)
827  {
828  for(unsigned int i=1; i<pano.getNrOfImages(); i++)
829  {
830  lenses.switchParts(i, lenses.getPartNumber(0));
831  };
832  };
833  if (pano.hasPossibleStacks())
834  {
835  pano.linkPossibleStacks(createLinks);
836  };
837  // Setup pano with options from preferences
839  //set default exposure value
840  opts.outputExposureValue = pano.getImage(0).getExposureValue();
841  wxConfigBase* config = wxConfigBase::Get();
842  opts.quality = config->Read(wxT("/output/jpeg_quality"),HUGIN_JPEG_QUALITY);
843  switch(config->Read(wxT("/output/tiff_compression"), HUGIN_TIFF_COMPRESSION))
844  {
845  case 0:
846  default:
847  opts.outputImageTypeCompression = "NONE";
848  opts.tiffCompression = "NONE";
849  break;
850  case 1:
851  opts.outputImageTypeCompression = "PACKBITS";
852  opts.tiffCompression = "PACKBITS";
853  break;
854  case 2:
855  opts.outputImageTypeCompression = "LZW";
856  opts.tiffCompression = "LZW";
857  break;
858  case 3:
859  opts.outputImageTypeCompression = "DEFLATE";
860  opts.tiffCompression = "DEFLATE";
861  break;
862  }
863  switch (config->Read(wxT("/output/ldr_format"), HUGIN_LDR_OUTPUT_FORMAT))
864  {
865  case 1:
866  opts.outputImageType ="jpg";
867  break;
868  case 2:
869  opts.outputImageType ="png";
870  break;
871  case 3:
872  opts.outputImageType ="exr";
873  break;
874  default:
875  case 0:
876  opts.outputImageType ="tif";
877  break;
878  }
880  opts.blendMode = defaultBlender;
881  opts.enblendOptions = config->Read(wxT("Enblend/Args"),wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
882  opts.enfuseOptions = config->Read(wxT("Enfuse/Args"),wxT(HUGIN_ENFUSE_ARGS)).mb_str(wxConvLocal);
883  opts.interpolator = (vigra_ext::Interpolator)config->Read(wxT("Nona/Interpolator"),HUGIN_NONA_INTERPOLATOR);
884  opts.tiff_saveROI = config->Read(wxT("Nona/CroppedImages"),HUGIN_NONA_CROPPEDIMAGES)!=0;
887  opts.verdandiOptions = config->Read(wxT("/VerdandiDefaultArgs"), wxEmptyString).mb_str(wxConvLocal);
888  pano.setOptions(opts);
889  // set optimizer switches
892 
893  if (pano.WritePTOFile(std::string(projectFile.GetFullPath().mb_str(HUGIN_CONV_FILENAME)),
894  std::string(projectFile.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR).mb_str(HUGIN_CONV_FILENAME))))
895  {
896  return projectFile.GetFullPath();
897  }
898  else
899  {
900  return wxEmptyString;
901  };
902 };
903 
905 {
906  return wxString(m_camera.c_str(), wxConvLocal);
907 }
908 
910 {
911  return wxString(m_lens.c_str(), wxConvLocal);
912 };
913 
915 {
916  if (!m_images.empty())
917  {
918  return FormatString::GetFocalLength(*m_images.begin());
919  };
920  return wxString::Format(wxT("%0.1f mm"), m_focallength);
921 };
922 
924 {
925  return m_dt_start.Format();
926 };
927 
929 {
930  wxTimeSpan diff = m_dt_end.Subtract(m_dt_start);
931  if (diff.GetSeconds() > 60)
932  {
933  return diff.Format(_("%M:%S min"));
934  }
935  else
936  {
937  return diff.Format(_("%S s"));
938  };
939 };
940 
941 void PossiblePano::PopulateListCtrl(wxListCtrl* list, wxImageList* thumbs, wxArrayString& tooltips)
942 {
943  list->DeleteAllItems();
944  thumbs->RemoveAll();
945  tooltips.Clear();
946  wxBusyCursor cursor;
947  for (ImageSet::iterator it = m_images.begin(); it != m_images.end(); ++it)
948  {
949 #if defined EXIV2_VERSION && EXIV2_TEST_VERSION(0,27,99)
950  Exiv2::Image::UniquePtr image;
951 #else
952  Exiv2::Image::AutoPtr image;
953 #endif
954  bool opened = false;
955  try
956  {
957  image = Exiv2::ImageFactory::open((*it)->getFilename().c_str());
958  opened = true;
959  }
960  catch (...)
961  {
962  std::cerr << __FILE__ << " " << __LINE__ << " Error opening file" << std::endl;
963  continue;
964  }
965  int index = -1;
966  if (opened)
967  {
968  try
969  {
970  image->readMetadata();
971  }
972  catch (const Exiv2::Error& e)
973  {
974  std::cerr << __FILE__ << " " << __LINE__ << " Exiv2: Error reading metadata (" << e.what() << ")" << std::endl;
975  continue;
976  }
977  // read all thumbnails
978  Exiv2::PreviewManager previews(*image);
979  Exiv2::PreviewPropertiesList lists = previews.getPreviewProperties();
980  if (!lists.empty())
981  {
982  // select a preview with matching size
983  int previewIndex = 0;
984  while (previewIndex < lists.size() - 1 && lists[previewIndex].width_ < THUMBSIZE && lists[previewIndex].height_ < THUMBSIZE)
985  {
986  ++previewIndex;
987  };
988  // load preview image to wxImage
989  wxImage rawImage;
990  Exiv2::PreviewImage previewImage = previews.getPreviewImage(lists[previewIndex]);
991  wxMemoryInputStream stream(previewImage.pData(), previewImage.size());
992  rawImage.LoadFile(stream, wxString(previewImage.mimeType().c_str(), wxConvLocal), -1);
993  int x = 0;
994  int y = 0;
995  if (previewImage.width() > previewImage.height())
996  {
997  //landscape format
998  int newHeight = THUMBSIZE*previewImage.height() / previewImage.width();
999  rawImage.Rescale(THUMBSIZE, newHeight);
1000  x = 0;
1001  y = (THUMBSIZE - newHeight) / 2;
1002  }
1003  else
1004  {
1005  //portrait format
1006  int newWidth = THUMBSIZE*previewImage.width() / previewImage.height();
1007  rawImage.Rescale(newWidth, THUMBSIZE);
1008  x = (THUMBSIZE - newWidth) / 2;
1009  y = 0;
1010  }
1011  // rotate according to orientation tag
1012  if ((*it)->getRoll() == 90)
1013  {
1014  rawImage = rawImage.Rotate90();
1015  std::swap(x, y);
1016  }
1017  else
1018  {
1019  if ((*it)->getRoll() == 270)
1020  {
1021  rawImage = rawImage.Rotate90(false);
1022  std::swap(x, y);
1023  }
1024  else
1025  {
1026  if ((*it)->getRoll() == 180)
1027  {
1028  rawImage = rawImage.Rotate180();
1029  };
1030  };
1031  };
1032  // create final bitmap with centered thumbnail
1033  wxBitmap bitmap(THUMBSIZE, THUMBSIZE);
1034  wxMemoryDC dc(bitmap);
1035  dc.SetBackground(list->GetBackgroundColour());
1036  dc.Clear();
1037  dc.DrawBitmap(rawImage, x, y);
1038  dc.SelectObject(wxNullBitmap);
1039  // create mask bitmap
1040  wxImage mask(THUMBSIZE, THUMBSIZE);
1041  mask.SetRGB(wxRect(0, 0, THUMBSIZE, THUMBSIZE), 0, 0, 0);
1042  mask.SetRGB(wxRect(x, y, THUMBSIZE - 2 * x, THUMBSIZE - 2 * y), 255, 255, 255);
1043  // add to wxImageList
1044  index = thumbs->Add(bitmap, wxBitmap(mask, 1));
1045  };
1046  };
1047  // create item in thumb list
1048  wxFileName fn(wxString((*it)->getFilename().c_str(), HUGIN_CONV_FILENAME));
1049  list->InsertItem(list->GetItemCount(), fn.GetFullName(), index);
1050  // build tooltip text
1051  tooltips.Add(fn.GetFullName() + "\n" + FormatString::GetAperture(*it) + ", "
1052  + FormatString::GetExposureTime(*it) + ", " + _("ISO") + FormatString::GetIso(*it)
1053  + "\n" + FormatString::GetExifDateTime(*it));
1054  };
1055 };
1056 
1057 void PossiblePano::RemoveImage(const unsigned int index)
1058 {
1059  // remove image with given index
1060  if (index < m_images.size())
1061  {
1062  ImageSet::iterator item = m_images.begin();
1063  std::advance(item, index);
1064  delete *item;
1065  m_images.erase(item);
1066  //update the internal times
1067  UpdateDateTimes();
1068  };
1069 }
1070 
1071 PossiblePano* PossiblePano::SplitPano(const unsigned int index)
1072 {
1073  PossiblePano* newPano = new PossiblePano();
1074  if (index < m_images.size())
1075  {
1076  // now move all images to right pano
1077  ImageSet allImages = m_images;
1078  m_images.clear();
1079  ImageSet::iterator img = allImages.begin();
1080  while (m_images.size() < index && img != allImages.end())
1081  {
1082  m_images.insert(*img);
1083  ++img;
1084  };
1085  while (img != allImages.end())
1086  {
1087  newPano->AddSrcPanoImage(*img);
1088  ++img;
1089  }
1090  UpdateDateTimes();
1091  };
1092  return newPano;
1093 }
1094 
1096 {
1097  // update internal stored start and end time
1098  m_dt_start = GetDateTime(*m_images.begin());
1099  m_dt_end = m_dt_start;
1100  for (auto& img : m_images)
1101  {
1102  wxDateTime dt = GetDateTime(img);
1103  if (dt.IsEarlierThan(m_dt_start))
1104  {
1105  m_dt_start = dt;
1106  }
1107  if (dt.IsLaterThan(m_dt_end))
1108  {
1109  m_dt_end = dt;
1110  };
1111  };
1112 }
std::string m_lens
wxString GetFocalLength()
returns the focal length as string
int alphanum_comp(const std::string &l, const std::string &r)
Compare l and r with the same semantics as strcmp(), but with the &quot;Alphanum Algorithm&quot; which produces...
Definition: alphanum.cpp:119
static void swap(T &x, T &y)
Definition: svm.cpp:67
#define HUGIN_NONA_CROPPEDIMAGES
unsigned int getPartNumber(unsigned int imageNr) const
Get a part number from an image number.
wxChoice * m_ch_naming
wxSpinCtrl * m_sc_maxTimeDiff
wxDateTime m_dt_start
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
void AddSrcPanoImage(HuginBase::SrcPanoImage *img)
adds the given SrcPanoImage to this pano-group
#define HUGIN_JPEG_QUALITY
~PossiblePano()
destructor, cleans up used variables
void setPhotometricOptimizerSwitch(const int newSwitch)
sets the photometric optimizer master switch
Definition: Panorama.cpp:311
Somewhere to specify what variables belong to what.
void AddToList(wxString aFile, Project::Target target=Project::STITCHING, wxString userDefined=wxEmptyString)
Definition: BatchFrame.cpp:489
void RemoveImage(const unsigned int index)
removes the image at given index
some helper classes for graphes
void EnableButtons(const bool state)
wxImageList * m_thumbs
wxButton * m_button_start
END_EVENT_TABLE()
include file for the hugin project
wxCheckBox * m_cb_loadDistortion
std::string outputImageTypeCompression
wxString GetCameraName()
returns the camera name
void setOptimizerSwitch(const int newSwitch)
set optimizer master switch
Definition: Panorama.cpp:303
wxCheckBox * m_cb_createLinks
ImageSet m_images
double m_cropfactor
Batch processor for Hugin with GUI.
int SortWxFilenames(const wxString &s1, const wxString &s2)
void OnButtonClose(wxCommandEvent &e)
closes window
wxCheckBox * m_cb_loadVignetting
void UpdateDateTimes()
updates the internal date/time representations
void linkPossibleStacks(bool linkPosition)
create automatically stacks as indicated by metadata
Definition: Panorama.cpp:2181
Model for a panorama.
Definition: Panorama.h:152
PossiblePano * SplitPano(const unsigned int index)
split pano into 2 subpanos, index is used as first image of second pano
BatchFrame * m_batchframe
wxArrayString m_tooltips
some definitions to work with optimizer master switches
size_t GetSelectedValue(wxControlWithItems *list)
Returns the client value of the selected item from list.
Definition: LensTools.cpp:102
wxDateTime m_dt_end
const wxString GetFilestring(const wxString BasePath, const bool stripExtension=false) const
returns a string with the filename of the first and last file
wxString GetDuration()
returns the duration as string
void PopulateListCtrl(wxListCtrl *list, wxImageList *thumbs, wxArrayString &tooltips)
add all images to wxListCtrl
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
void SearchInDir(wxString dirstring, const bool includeSubdir, const bool loadDistortion, const bool loadVignetting, const size_t minNumberImages, const size_t maxTimeDiff)
const int getExifDateTime(struct tm *datetime) const
try to convert Exif date time string to struct tm
void OnSplitPanos(wxCommandEvent &e)
event handler to split into 2 panos
vigra_ext::Interpolator interpolator
const unsigned int GetImageCount() const
returns number of images in this group
Definition of dialog to change user defined sequence.
wxString GetStartString()
return the start date/time as string
ImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
#define HUGIN_NONA_INTERPOLATOR
#define HUGIN_TIFF_COMPRESSION
void OnListMouseMove(wxMouseEvent &e)
mouse move handler for tooltips
wxCheckBox * m_cb_subdir
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
Definition: SrcPanoImage.h:55
wxString GetLensName()
returns the lens name
std::set< HuginBase::SrcPanoImage *, SortFilename > ImageSet
IMPEX double h[25][1024]
Definition: emor.cpp:169
std::string stripExtension(const std::string &basename2)
remove extension of a filename
Definition: utils.cpp:130
TIFFErrorHandler m_oldtiffwarning
void OnSelectPossiblePano(wxCommandEvent &e)
event to populate information on the right
wxStaticText * m_statustext
void OnListItemRightClick(wxListEvent &e)
event handler for context menu
#define HUGIN_HDRMERGE_ARGS
#define HUGIN_LDR_OUTPUT_FORMAT
bool BelongsTo(HuginBase::SrcPanoImage *img, const wxTimeSpan max_time_diff)
return true, if the image could belong to the given PossiblePano, it checks camera maker and model...
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition: Panorama.cpp:319
wxTextCtrl * m_textctrl_dir
wxString GetExposureTime(const HuginBase::SrcPanoImage *img)
returns formatted exposure time
Definition: LensTools.cpp:554
Same as above, but use a non const panorama.
wxButton * m_button_close
NamingConvention
enumeration for different naming conventions, must be match combobox in ressource ...
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
wxString GeneratePanorama(NamingConvention nc, bool createLinks, HuginBase::PanoramaOptions::BlendingMechanism defaultBlender)
generates the panorama file from this set of images
wxString GetExifDateTime(const HuginBase::SrcPanoImage *img)
returns Exif DateTimeOriginal as formatted wxString
Definition: LensTools.cpp:503
#define THUMBSIZE
void SelectListValue(wxControlWithItems *list, size_t newValue)
Selects the given value (stored in the client data) in the given list item.
Definition: LensTools.cpp:89
wxListCtrl * m_thumbsList
vigra::Size2D m_size
double m_focallength
wxString m_start_dir
bool GetNewProjectFilename(NamingConvention nc, const wxString basePath, wxFileName &projectFile)
returns a given filename, which does not already exists
#define HUGIN_ENFUSE_ARGS
bool readEXIF()
try to fill out information about the image, by examining the exif data
const wxDateTime GetDateTime(const HuginBase::SrcPanoImage *img)
does some reformating date/time format
PossiblePano()
constructor, init values
void OnClose(wxCloseEvent &e)
prevents closing window when running detection
platform/compiler specific stuff.
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
wxSpinCtrl * m_sc_minNumberImages
~FindPanoDialog()
destructor, saves size and position
std::string m_camera
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
FindPanoDialog(BatchFrame *batchframe, wxString xrcPrefix)
Constructor, read from xrc ressource; restore last uses settings, size and position.
const wxString GetItemString(const wxString BasePath) const
returns a string which contains description of this pano
void OnRemoveImage(wxCommandEvent &e)
event handler to remove selected image from list
void setOptions(const PanoramaOptions &opt)
set new output settings This is not used directly for optimizing/stiching, but it can be feed into ru...
Definition: Panorama.cpp:1531
wxString GetFocalLength(const HuginBase::SrcPanoImage *img)
return focallength and focallength 35 mm as wxString
Definition: LensTools.cpp:519
Dialog for finding panorama in given directory.
Interpolator
enum with all interpolation methods
Definition: Interpolators.h:78
static uint16_t flags
All variables of a source image.
Definition: SrcPanoImage.h:194
Panorama image options.
wxString GetAperture(const HuginBase::SrcPanoImage *img)
returns formatted aperture value
Definition: LensTools.cpp:540
void switchParts(unsigned int ImageNr, unsigned int partNr)
switch a given image to a different part number.
const bool hasPossibleStacks() const
return true, if the metadata indicates that the projects is a bracketet project
Definition: Panorama.cpp:2137
wxButton * m_button_choose
#define HUGIN_ENBLEND_ARGS
wxChoice * m_ch_blender
void OnButtonSend(wxCommandEvent &e)
add selected projects to queue
wxString getDefaultProjectName(const HuginBase::Panorama &pano, const wxString filenameTemplate)
gets the default project name, as defined in the preferences
void OnButtonChoose(wxCommandEvent &e)
select directory with dialog
BlendingMechanism blendMode
std::string m_make
wxCheckListBox * m_list_pano
void FillBlenderList(wxControlWithItems *list)
Fills a wxControlWithItem with all possible blender options, the client data contains the associated ...
Definition: LensTools.cpp:81
wxString GetIso(const HuginBase::SrcPanoImage *img)
returns formatted iso value
Definition: LensTools.cpp:591
wxButton * m_button_send
void OnButtonStart(wxCommandEvent &e)
start/stops detections
std::vector< PossiblePano * > m_panos