Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PerspectivePanel.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
10 /* This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This software is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public
21  * License along with this software. If not, see
22  * <http://www.gnu.org/licenses/>.
23  *
24  */
25 
26 #include "PerspectivePanel.h"
27 #include "ToolboxApp.h"
28 #include "base_wx/platform.h"
29 #include "wx/clrpicker.h"
30 #include "hugin/config_defaults.h"
31 #include "base_wx/wxPlatform.h"
32 #include "panodata/Panorama.h"
34 #include "base_wx/PTWXDlg.h"
40 #include "lines/FindLines.h"
41 #include "wx/stdpaths.h"
42 #include "base_wx/Executor.h"
43 #include "base_wx/wxutils.h"
44 
46 class PerspectiveDropTarget : public wxFileDropTarget
47 {
48 public:
49  PerspectiveDropTarget(PerspectivePanel* parent) : wxFileDropTarget()
50  {
51  m_perspectivePanel = parent;
52  }
53 
54  bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString& filenames)
55  {
56  // try to add as images
57  if (filenames.size() == 1)
58  {
59  wxFileName file(filenames[0]);
60  if (file.GetExt().CmpNoCase("jpg") == 0 ||
61  file.GetExt().CmpNoCase("jpeg") == 0 ||
62  file.GetExt().CmpNoCase("tif") == 0 ||
63  file.GetExt().CmpNoCase("tiff") == 0 ||
64  file.GetExt().CmpNoCase("png") == 0 ||
65  file.GetExt().CmpNoCase("bmp") == 0 ||
66  file.GetExt().CmpNoCase("gif") == 0 ||
67  file.GetExt().CmpNoCase("pnm") == 0)
68  {
69  m_perspectivePanel->SetImage(filenames[0]);
70  return true;
71  }
72  else
73  {
74  wxBell();
75  };
76  }
77  else
78  {
79  wxBell();
80  };
81  return false;
82  }
83 private:
85 };
86 
87 bool PerspectivePanel::Create(wxWindow* parent, MyExecPanel* logWindow)
88 {
89  if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, "panel"))
90  {
91  return false;
92  };
93  // create image control
95  m_preview->Create(this);
96  // set to scale to window
97  m_preview->setScale(0);
98  // load from xrc file
99  wxXmlResource::Get()->LoadPanel(this, "perspective_panel");
100  // connect image control
101  wxXmlResource::Get()->AttachUnknownControl("perspective_preview_window", m_preview, this);
102  // add to sizer
103  wxPanel* mainPanel = XRCCTRL(*this, "perspective_panel", wxPanel);
104  wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
105  topsizer->Add(mainPanel, wxSizerFlags(1).Expand());
106  SetSizer(topsizer);
107  // remember some pointer to controls for easier access
108  m_focallengthTextCtrl = XRCCTRL(*this, "perspective_focallength", wxTextCtrl);
109  m_cropTextCtrl = XRCCTRL(*this, "perspective_cropfactor", wxTextCtrl);
110  m_previewChoice = XRCCTRL(*this, "perspective_preview", wxChoice);
111  m_zoomChoice = XRCCTRL(*this, "perspective_choice_zoom", wxChoice);
112  m_rotationChoice = XRCCTRL(*this, "perspective_rotation", wxChoice);
113  m_modeChoice = XRCCTRL(*this, "perspective_mode", wxChoice);
114  m_findLineButton = XRCCTRL(*this, "perspective_find_lines", wxButton);
115  m_helpTextCtrl = XRCCTRL(*this, "perspective_help_text", wxStaticText);
116 #if wxCHECK_VERSION(3,3,2)
117  m_helpTextCtrl->SetWindowStyle(m_helpTextCtrl->GetWindowStyle() | wxST_WRAP);
118 #endif
119  m_outputButton = XRCCTRL(*this, "perspective_output", wxButton);
120  m_logWindow = logWindow;
121 
122  wxConfigBase* config = wxConfigBase::Get();
123  //load and set colour
124  wxColour colour, defaultColour;
125  defaultColour.Set(HUGIN_MASK_COLOUR_POINT_SELECTED);
126  colour = config->Read("/ToolboxFrame/Perspective/LineColour", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
127  XRCCTRL(*this, "perspective_color_picker", wxColourPickerCtrl)->SetColour(colour);
128  m_preview->SetLineColour(colour);
129  m_degDigits = config->Read("/General/DegreeFractionalDigitsEdit", 3);
130 
131  // bind event handler
132  Bind(wxEVT_BUTTON, &PerspectivePanel::OnLoadImage, this, XRCID("perspective_load"));
133  Bind(wxEVT_BUTTON, &PerspectivePanel::OnSavePTO, this, XRCID("perspective_output_pto"));
134  m_outputButton->Bind(wxEVT_BUTTON, &PerspectivePanel::OnSaveOutput, this);
135  m_previewChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnPreview, this);
136  m_zoomChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnZoom, this);
137  m_modeChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnModeChanged, this);
138  Bind(wxEVT_CHOICE, &PerspectivePanel::OnCropChanged, this, XRCID("perspective_crop"));
139  m_rotationChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnRotationChanged, this);
140  m_findLineButton->Bind(wxEVT_BUTTON, &PerspectivePanel::OnFindLines, this);
141  Bind(wxEVT_COLOURPICKER_CHANGED, &PerspectivePanel::OnColourChanged, this, XRCID("perspective_color_picker"));
142  // update help text
143  wxCommandEvent commandEvent;
144  OnModeChanged(commandEvent);
145  // allow dropping files
146  SetDropTarget(new PerspectiveDropTarget(this));
147  return true;
148 }
149 
150 void PerspectivePanel::OnZoom(wxCommandEvent& e)
151 {
152  double factor;
153  switch (e.GetSelection())
154  {
155  case 0:
156  factor = 1;
157  break;
158  case 1:
159  // fit to window
160  factor = 0;
161  break;
162  case 2:
163  factor = 2;
164  break;
165  case 3:
166  factor = 1.5;
167  break;
168  case 4:
169  factor = 0.75;
170  break;
171  case 5:
172  factor = 0.5;
173  break;
174  case 6:
175  factor = 0.25;
176  break;
177  default:
178  DEBUG_ERROR("unknown scale factor");
179  factor = 1;
180  }
181  m_preview->setScale(factor);
182 }
183 
184 void PerspectivePanel::OnPreview(wxCommandEvent& e)
185 {
186  if (m_previewChoice->GetSelection() == 1)
187  {
188  // preview mode
189  HuginBase::Panorama pano;
190  if (GetPanorama(pano))
191  {
192  // disable zoom choice in preview mode
193  m_zoomChoice->Enable(e.GetSelection() == 0);
194  m_preview->SetRemappedMode(pano);
195  }
196  else
197  {
198  // could not create pano, reset selection
199  m_previewChoice->SetSelection(0);
200  m_zoomChoice->Enable();
202  }
203  }
204  else
205  {
206  // show original
207  m_zoomChoice->Enable();
209  };
210  Refresh();
211  e.Skip();
212 }
213 
214 void PerspectivePanel::SetImage(const wxString& filename)
215 {
216  // update label for display of filename
217  XRCCTRL(*this, "perspective_filename", wxStaticText)->SetLabel(filename);
218  Layout();
219  // create HuginBase::SrcPanoImage and load values from EXIF
221  const std::string filenameString(filename.mb_str(HUGIN_CONV_FILENAME));
222  m_srcImage.setFilename(filenameString);
224  m_focallengthTextCtrl->Clear();
225  m_cropTextCtrl->Clear();
227  if (m_srcImage.readEXIF())
228  {
229  bool ok = m_srcImage.applyEXIFValues();
230  // load crop factor from database if unknown
231  if (m_srcImage.getCropFactor() < 0.1)
232  {
234  ok = (m_srcImage.getExifFocalLength() > 0 && m_srcImage.getCropFactor() > 0.1);
235  };
236  // update values in control
237  const double focallength = HuginBase::SrcPanoImage::calcFocalLength(m_srcImage.getProjection(), m_srcImage.getHFOV(), m_srcImage.getCropFactor(), m_srcImage.getSize());;
238  const double cropFactor = m_srcImage.getCropFactor();
239  if (focallength > 0 && focallength < 10000)
240  {
241  // use ChangeValue explicit, SetValue would create EVT_TEXT event which collides with our TextKillFocusHandler
243  };
244  if (cropFactor > 0 && cropFactor < 1000)
245  {
246  m_cropTextCtrl->ChangeValue(hugin_utils::doubleTowxString(cropFactor, m_degDigits));
247  };
248  const double rotation = m_srcImage.getExifOrientation();
249  if (rotation == 90)
250  {
252  }
253  else
254  {
255  if (rotation == 180)
256  {
258  }
259  else
260  {
261  if (rotation == 270)
262  {
264  };
265  };
266  };
267  };
268  m_preview->setImage(filenameString, GetRotation());
269  // reset preview mode to original
270  wxCommandEvent e;
271  m_previewChoice->SetSelection(0);
272  OnPreview(e);
273 }
274 
275 void PerspectivePanel::OnLoadImage(wxCommandEvent& e)
276 {
277  wxConfigBase* config = wxConfigBase::Get();
278  wxString path = config->Read("/actualPath", "");
279  wxFileDialog dlg(this, _("Add images"), path, wxEmptyString, GetFileDialogImageFilters(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_PREVIEW, wxDefaultPosition);
280  dlg.SetDirectory(path);
281 
282  // remember the image extension
283  wxString img_ext;
284  if (config->HasEntry("lastImageType"))
285  {
286  img_ext = config->Read("lastImageType").c_str();
287  }
288  if (img_ext == "all images")
289  dlg.SetFilterIndex(0);
290  else if (img_ext == "jpg")
291  dlg.SetFilterIndex(1);
292  else if (img_ext == "tiff")
293  dlg.SetFilterIndex(2);
294  else if (img_ext == "png")
295  dlg.SetFilterIndex(3);
296  else if (img_ext == "hdr")
297  dlg.SetFilterIndex(4);
298  else if (img_ext == "exr")
299  dlg.SetFilterIndex(5);
300  else if (img_ext == "all files")
301  dlg.SetFilterIndex(6);
302 
303  // call the file dialog
304  if (dlg.ShowModal() == wxID_OK)
305  {
306  // display the selected image
307  SetImage(dlg.GetPath());
308  // save the current path to config
309  config->Write("/actualPath", dlg.GetDirectory());
310  // save the image extension
311  switch (dlg.GetFilterIndex())
312  {
313  case 0: config->Write("lastImageType", "all images"); break;
314  case 1: config->Write("lastImageType", "jpg"); break;
315  case 2: config->Write("lastImageType", "tiff"); break;
316  case 3: config->Write("lastImageType", "png"); break;
317  case 4: config->Write("lastImageType", "hdr"); break;
318  case 5: config->Write("lastImageType", "exr"); break;
319  case 6: config->Write("lastImageType", "all files"); break;
320  };
321  };
322 }
323 
324 void PerspectivePanel::OnColourChanged(wxColourPickerEvent& e)
325 {
326  m_preview->SetLineColour(e.GetColour());
327  wxConfigBase::Get()->Write("/ToolboxFrame/Perspective/LineColour", e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
328 }
329 
330 void PerspectivePanel::OnCropChanged(wxCommandEvent& e)
331 {
332  if (!m_preview->IsOriginalShown())
333  {
334  // refresh preview
335  OnPreview(e);
336  };
337 }
338 
339 void PerspectivePanel::OnRotationChanged(wxCommandEvent& e)
340 {
342  if (!m_preview->IsOriginalShown())
343  {
344  // refresh preview
345  OnPreview(e);
346  };
347 }
348 
349 void PerspectivePanel::OnModeChanged(wxCommandEvent& e)
350 {
351  const bool isRectMode = m_modeChoice->GetSelection() == 0;
352  m_preview->SetRectMode(isRectMode);
353  if (!m_preview->IsOriginalShown())
354  {
355  // set mode back to original
356  m_previewChoice->SetSelection(0);
357  // refresh preview
358  OnPreview(e);
359  };
360  m_findLineButton->Enable(!isRectMode);
361  m_findLineButton->Show(!isRectMode);
362  // update help text
363  m_helpTextCtrl->SetLabel(GetStatusString());
364  m_helpTextCtrl->Wrap(XRCCTRL(*this, "perspective_color_picker", wxColourPickerCtrl)->GetSize().GetWidth());
365  Layout();
366 }
367 
368 void PerspectivePanel::OnFindLines(wxCommandEvent& e)
369 {
370  HuginBase::Panorama pano;
371  // get unoptimized pano
372  if (GetPanorama(pano, false))
373  {
374  // find lines
375  HuginBase::CPVector lines;
376  if (wxGetKeyState(WXK_COMMAND))
377  {
378  lines = HuginLines::GetVerticalLines(pano, 0, *(m_preview->getCachedImage()->get8BitImage()), *(m_preview->getCachedImage()->mask), 10);
379  }
380  else
381  {
382  lines = HuginLines::GetLines(pano, 0, *(m_preview->getCachedImage()->get8BitImage()), *(m_preview->getCachedImage()->mask));
383  };
384  if (!lines.empty())
385  {
386  // add them to image control
387  m_preview->AddLines(lines);
388  // reset preview mode to original
389  m_previewChoice->SetSelection(0);
390  OnPreview(e);
391  };
392  };
393 }
394 
395 void PerspectivePanel::OnSavePTO(wxCommandEvent& e)
396 {
397  HuginBase::Panorama pano;
398  wxConfigBase* config = wxConfigBase::Get();
399  wxString path = config->Read("/actualPath", "");
400 
401  if (GetPanorama(pano))
402  {
403  wxFileDialog dlg(this, _("Save project file"), path, wxEmptyString,
404  _("Project files (*.pto)|*.pto|All files (*)|*"),
405  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
406  if (dlg.ShowModal() == wxID_OK)
407  {
408  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
409  wxString fn = dlg.GetPath();
410  if (fn.Right(4).CmpNoCase(".pto") != 0)
411  {
412  fn.Append(".pto");
413  if (wxFile::Exists(fn))
414  {
415  if (!hugin_utils::AskUserOverwrite(fn , _("Hugin toolbox"), this))
416  {
417  return;
418  };
419  };
420  };
421  const std::string script(fn.mb_str(HUGIN_CONV_FILENAME));
422  pano.WritePTOFile(script, hugin_utils::getPathPrefix(script));
423  };
424  };
425  m_preview->SendSizeEvent();
426 }
427 
428 void PerspectivePanel::OnSaveOutput(wxCommandEvent& e)
429 {
430  HuginBase::Panorama pano;
431  if (GetPanorama(pano))
432  {
433  wxConfigBase* config = wxConfigBase::Get();
434  wxString path = config->Read("/actualPath", "");
435  wxFileDialog dlg(this, _("Save output"), path, wxEmptyString, GetMainImageFilters(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
436  dlg.SetDirectory(path);
437 
438  // remember the image extension
439  wxString img_ext;
440  if (config->HasEntry("lastImageType"))
441  {
442  img_ext = config->Read("lastImageType").c_str();
443  };
444  if (img_ext == "jpg")
445  {
446  dlg.SetFilterIndex(0);
447  }
448  else
449  {
450  if (img_ext == "tiff")
451  {
452  dlg.SetFilterIndex(1);
453  }
454  else
455  {
456  if (img_ext == "png")
457  {
458  dlg.SetFilterIndex(2);
459  };
460  };
461  };
462  wxFileName outputfilename(wxString(m_srcImage.getFilename().c_str(), HUGIN_CONV_FILENAME));
463  wxString inputFilename = outputfilename.GetFullPath();
464  outputfilename.SetName(outputfilename.GetName() + "_corrected");
465  dlg.SetFilename(outputfilename.GetFullPath());
466  // call the file dialog
467  if (dlg.ShowModal() == wxID_OK)
468  {
469  std::string outputFilename(dlg.GetPath().mb_str(HUGIN_CONV_FILENAME));
470  // save the current path to config
471  config->Write("/actualPath", dlg.GetDirectory());
472  // save the image extension
473  wxString tempFilename = wxFileName::CreateTempFileName(HuginQueue::GetConfigTempDir(wxConfig::Get()) + "htb");
474  pano.WritePTOFile(std::string(tempFilename.mb_str(HUGIN_CONV_FILENAME)));
475  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
476  wxString nonaArgs;
477  switch (dlg.GetFilterIndex())
478  {
479  case 0:
480  config->Write("lastImageType", "jpg");
481  nonaArgs.Append("-m JPEG ");
482  break;
483  case 1:
484  default:
485  config->Write("lastImageType", "tiff");
486  nonaArgs.Append("-m TIFF ");
487  break;
488  case 2:
489  config->Write("lastImageType", "png");
490  nonaArgs.Append("-m PNG ");
491  break;
492  };
493  // use nona for remapping
494  nonaArgs.Append("-v -o " + HuginQueue::wxEscapeFilename(dlg.GetPath()) + " " + HuginQueue::wxEscapeFilename(tempFilename));
496  queue->push_back(new HuginQueue::NormalCommand(HuginQueue::GetInternalProgram(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), "nona"), nonaArgs, _("Remapping image")));
497  wxString exiftoolArgs("-overwrite_original -tagsfromfile ");
498  exiftoolArgs.Append(HuginQueue::wxEscapeFilename(wxString(m_srcImage.getFilename().c_str(), HUGIN_CONV_FILENAME)));
499  // tags to copy and to ignore (white space at begin and at end!)
500  exiftoolArgs.Append(" -all:all --thumbnail --thumbnailimage --xposition --yposition --orientation --imagefullwidth --imagefullheight ");
501  exiftoolArgs.Append(HuginQueue::wxEscapeFilename(dlg.GetPath()));
502  queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), "exiftool"), exiftoolArgs, _("Updating EXIF")));
503  m_tempFiles.Add(tempFilename);
505  m_logWindow->ExecQueue(queue);
506  m_outputButton->Disable();
507  };
508  };
509 }
510 
511 void PerspectivePanel::OnProcessFinished(wxCommandEvent& e)
512 {
513  if (!m_tempFiles.IsEmpty())
514  {
515  // delete all temporary files at the end of command
516  for (auto& file : m_tempFiles)
517  {
518  if (wxFileExists(file))
519  {
520  wxRemoveFile(file);
521  };
522  };
523  m_tempFiles.clear();
524  };
525  m_outputButton->Enable();
526 }
527 
529 {
530  if (m_modeChoice->GetSelection()==0)
531  {
532  return _("Adjust the rectangle to an area which should be rectangular in the projected image.");
533  }
534  else
535  {
536  return _("Create a new line by dragging with left mouse button on a free space.\nExisting lines or line end points can be moved by dragging with left mouse button.\nA line can be deleted by clicking with the right mouse button.");
537  };
538 }
539 
541 {
542  if (m_srcImage.getFilename().empty())
543  {
544  hugin_utils::HuginMessageBox(_("You need to load an image first."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
545  return false;
546  }
547  wxString focallengthText = m_focallengthTextCtrl->GetValue();
548  if (focallengthText.IsEmpty())
549  {
550  hugin_utils::HuginMessageBox(_("Focal length input box is empty."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
551  return false;
552  };
553  double focallength, cropfactor;
554  if (!hugin_utils::str2double(focallengthText, focallength))
555  {
556  hugin_utils::HuginMessageBox(_("Focal length input box contains no valid number."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
557  return false;
558  }
559  //no negative values, no zero input please
560  if (focallength < 0.1)
561  {
562  hugin_utils::HuginMessageBox(_("The focal length must be positive."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
563  return false;
564  };
565  wxString cropfactorText = m_cropTextCtrl->GetValue();
566  if (cropfactorText.IsEmpty())
567  {
568  hugin_utils::HuginMessageBox(_("Crop factor input box is empty."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
569  return false;
570  };
571  if (!hugin_utils::str2double(cropfactorText, cropfactor))
572  {
573  hugin_utils::HuginMessageBox(_("Crop factor input box contains no valid number."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
574  return false;
575  }
576  //no negative values, no zero input please
577  if (cropfactor < 0.1)
578  {
579  hugin_utils::HuginMessageBox(_("The crop factor must be positive."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
580  return false;
581  };
582  const double hfov = HuginBase::SrcPanoImage::calcHFOV(m_srcImage.getProjection(), focallength, cropfactor, m_srcImage.getSize());
583  if (hfov > 178)
584  {
585  hugin_utils::HuginMessageBox(_("The focal length and crop factor result in a invalid value of %d for the horizontal field of view.\nPlease input a valid combination of focal length and crop factor."),
586  _("Hugin toolbox"), wxICON_QUESTION | wxOK, this);
587  return false;
588  };
589  m_srcImage.setHFOV(hfov);
590  return true;
591 }
592 
593 bool PerspectivePanel::GetPanorama(HuginBase::Panorama& pano, const bool optimized)
594 {
595  if (ReadInputs())
596  {
598  panoImage.setRoll(GetRoll());
599  pano.addImage(panoImage);
601  if (optimized && pano.getCtrlPoints().size() < 2)
602  {
603  hugin_utils::HuginMessageBox(_("You need to create at least 2 lines."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
604  return false;
605  };
607  // optimize yaw, pitch and roll
608  std::set<std::string> imgopt;
609  imgopt.insert("y");
610  imgopt.insert("p");
611  imgopt.insert("r");
612  optvec.push_back(imgopt);
613  pano.setOptimizeVector(optvec);
614  // set some sensible values for PanoramaOptions
617  opts.outputExposureValue = m_srcImage.getExposureValue();
618  pano.setOptions(opts);
619  // now optimize pano
620  if (optimized)
621  {
625  // calculate field of view
626  HuginBase::CalculateFitPanorama fitPano(pano);
627  fitPano.run();
628  opts.setHFOV(fitPano.getResultHorizontalFOV());
630  // calculate scale
632  opts.setWidth(scale * opts.getWidth());
633  pano.setOptions(opts);
634  // crop pano
636  const int cropMode = XRCCTRL(*this, "perspective_crop", wxChoice)->GetSelection();
637  if (cropMode == 1)
638  {
639  // crop inside
640  HuginBase::CalculateOptimalROI cropPano(pano, &progress);
641  cropPano.run();
642  if (cropPano.hasRunSuccessfully())
643  {
644  opts.setROI(cropPano.getResultOptimalROI());
645  };
646  pano.setOptions(opts);
647  }
648  else
649  {
650  // crop outside
651  HuginBase::CalculateOptimalROIOutside cropPano(pano, &progress);
652  cropPano.run();
653  if (cropPano.hasRunSuccessfully())
654  {
655  opts.setROI(cropPano.getResultOptimalROI());
656  };
657  pano.setOptions(opts);
658  };
659  };
660  return true;
661  }
662  else
663  {
664  return false;
665  };
666 }
667 
669 {
670  switch (m_rotationChoice->GetSelection())
671  {
672  case 0:
673  default:
674  // auto-rotate, return EXIF value
675  return m_exifRotation;
676  break;
677  case 1:
679  break;
680  case 2:
682  break;
683  case 3:
685  break;
686  case 4:
688  break;
689  }
691 }
692 
693 const double PerspectivePanel::GetRoll() const
694 {
695  switch (GetRotation())
696  {
698  default:
699  return 0.0;
700  break;
702  return 90.0;
703  break;
705  return 180.0;
706  break;
708  return 270.0;
709  break;
710  }
711  return 0.0;
712 }
713 
wxArrayString m_tempFiles
temp files, which should be deleted at end
normal command for queue, processing is stopped if an error occurred in program
Definition: Executor.h:37
wxTextCtrl * m_cropTextCtrl
bool Create(wxWindow *parent, MyExecPanel *logWindow)
create the panel and populate all controls
implementation of huginApp Class
Dummy progress display, without output.
bool AskUserOverwrite(const wxString &filename, const wxString &caption, wxWindow *parent)
ask user if the given file should be overwritten, return true if the user confirmed the overwritting ...
Definition: wxutils.cpp:233
static double calcOptimalPanoScale(const SrcPanoImage &src, const PanoramaOptions &dest)
function to calculate the scaling factor so that the distances in the input image and panorama image ...
wxString GetStatusString()
return help text for current mode
void OnFindLines(wxCommandEvent &e)
bool applyEXIFValues(bool applyEVValue=true)
apply values found in EXIF data to SrcPanoImage class, call readEXIF() before to initialize some valu...
const wxString GetConfigTempDir(const wxConfigBase *config)
return the temp dir from the preferences, ensure that it ends with path separator ...
Definition: Executor.cpp:302
void setHeight(unsigned int h)
set panorama height
int roundi(T x)
Definition: hugin_math.h:73
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
HuginBase::CPVector GetVerticalLines(const HuginBase::Panorama &pano, const unsigned int imgNr, vigra::UInt8RGBImage &image, vigra::BImage &mask, const unsigned int nrLines)
searches for vertical control points in given image
Definition: FindLines.cpp:601
optional command for queue, processing of queue is always continued, also if an error occurred ...
Definition: Executor.h:53
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
declaration of panel for perspective correction GUI
wxButton * m_outputButton
declaration of functions for finding lines
wxStaticText * m_helpTextCtrl
void registerPTWXDlgFcn()
Definition: PTWXDlg.cpp:178
int ExecQueue(HuginQueue::CommandQueue *queue)
bool checkImageSizeKnown()
check if the image size is known, if try to load the information from the file
void ChangeRotation(ImageRotation newRot)
void OnModeChanged(wxCommandEvent &e)
void ClearOutput()
clear the output
void deregisterPTWXDlgFcn()
Definition: PTWXDlg.cpp:185
wxString doubleTowxString(double d, int digits)
Definition: wxPlatform.cpp:31
wxString GetInternalProgram(const wxString &bindir, const wxString &name)
return path and name of external program, which comes bundled with Hugin
Definition: Executor.cpp:129
const double GetRoll() const
return the roll angle in degree
void setScale(double factor)
set the scaling factor for mask editing display.
void SetRectMode(bool newMode)
set line or rect mode
virtual void run()
runs the algorithm.
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
void setOptimizeVector(const OptimizeVector &optvec)
set optimize setting
Definition: Panorama.cpp:297
PerspectivePanel * m_perspectivePanel
basic classes and function for queuing commands in wxWidgets
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
creates the control
void setImage(const std::string &filename, ImageRotation rot)
set the current image and mask list, this loads also the image from cache
bool ReadInputs()
read the values from the input boxes
void SetRemappedMode(const HuginBase::Panorama &pano)
set the panorama object for remapping, the mouse handler are deactivated
PerspectiveImageCtrl::ImageRotation m_exifRotation
save rotation as written in EXIF
Model for a panorama.
Definition: Panorama.h:152
void AddLines(const HuginBase::CPVector &lines)
add the lines to the list
std::string getPathPrefix(const std::string &filename)
Get the path to a filename.
Definition: utils.cpp:184
wxChoice * m_modeChoice
void OnProcessFinished(wxCommandEvent &e)
clean up temporary files at end
const PerspectiveImageCtrl::ImageRotation GetRotation() const
return the image rotation
void OnSaveOutput(wxCommandEvent &e)
void OnZoom(wxCommandEvent &e)
HuginBase::CPVector GetControlPoints(const unsigned int index)
return list of control points
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be &#39;add&#39; method?)
Definition: Panorama.cpp:449
void OnLoadImage(wxCommandEvent &e)
virtual vigra::Rect2D getResultOptimalROI()
return the ROI structure?, for now area
virtual double getResultHeight()
Definition: FitPanorama.h:75
void SetLineColour(wxColour newColour)
sets the colour for the lines
PerspectiveImageCtrl * m_preview
controls
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
wxString GetMainImageFilters()
return a filter for the main image files (JPG/TIFF/PNG) only
Definition: platform.cpp:81
bool GetPanorama(HuginBase::Panorama &pano, const bool optimized=true)
return Pano object, it is optimized and the crop set when optimized=true
wxChoice * m_zoomChoice
HuginBase::CPVector GetLines(const HuginBase::Panorama &pano, const unsigned int imgNr, vigra::UInt8RGBImage &image, vigra::BImage &mask)
searches for all lines, the same as GetVerticalLines execpt that no filtering according to roll angle...
Definition: FindLines.cpp:611
image previewer for perspective correction
static double calcFocalLength(SrcPanoImage::Projection proj, double hfov, double crop, vigra::Size2D imageSize)
calcualte focal length, given crop factor and hfov
ImageCache::EntryPtr getCachedImage()
return pointer to ImageCache
MyExecPanel * m_logWindow
#define DEBUG_ERROR(msg)
Definition: utils.h:76
void setROI(const vigra::Rect2D &val)
!! from PTOptimise.h 1951
unsigned int addImage(const SrcPanoImage &img)
the the number for a specific image
Definition: Panorama.cpp:319
bool OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &filenames)
void setOriginalMode()
show the original images with selected zoom ration, the mouse handlers are activated ...
void OnCropChanged(wxCommandEvent &e)
void OnRotationChanged(wxCommandEvent &e)
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
wxButton * m_findLineButton
unsigned int getWidth() const
ImageRotation
image rotation.
void OnColourChanged(wxColourPickerEvent &e)
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
virtual vigra::Rect2D getResultOptimalROI()
returns the found crop rect
str wxEscapeFilename(const str &arg)
special escaping routine for CommandQueues
Definition: Executor.h:79
#define HUGIN_MASK_COLOUR_POINT_SELECTED
bool readEXIF()
try to fill out information about the image, by examining the exif data
file drag and drop handler method
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
static double calcHFOV(SrcPanoImage::Projection proj, double fl, double crop, vigra::Size2D imageSize)
calculate hfov of an image given focal length, image size and crop factor
platform/compiler specific stuff.
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
std::vector< std::set< std::string > > OptimizeVector
void OnSavePTO(wxCommandEvent &e)
HuginBase::SrcPanoImage m_srcImage
SrcPanoImage, contains information about the image.
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
void OnPreview(wxCommandEvent &e)
wxTextCtrl * m_focallengthTextCtrl
void SetImage(const wxString &filename)
load the given image
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
wxString GetFileDialogImageFilters()
return filter for image files, needed by file open dialog it contains all image format vigra can read...
Definition: platform.cpp:70
Panorama image options.
bool readCropfactorFromDB()
tries to read cropfactor from lens database you need to call SrcPanoImage::readEXIF before to fill so...
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
wxString GetExternalProgram(wxConfigBase *config, const wxString &bindir, const wxString &name)
return path and name of external program, which can be overwritten by the user
Definition: Executor.cpp:148
std::vector< NormalCommand * > CommandQueue
Definition: Executor.h:61
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
panel for enfuse GUI
wxChoice * m_previewChoice
PerspectiveDropTarget(PerspectivePanel *parent)
wxChoice * m_rotationChoice