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 // destructor, save settings
89 {
90  wxConfigBase* config = wxConfigBase::Get();
91  config->Flush();
92 }
93 
94 bool PerspectivePanel::Create(wxWindow* parent, MyExecPanel* logWindow)
95 {
96  if (!wxPanel::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, "panel"))
97  {
98  return false;
99  };
100  // create image control
102  m_preview->Create(this);
103  // set to scale to window
104  m_preview->setScale(0);
105  // load from xrc file
106  wxXmlResource::Get()->LoadPanel(this, "perspective_panel");
107  // connect image control
108  wxXmlResource::Get()->AttachUnknownControl("perspective_preview_window", m_preview, this);
109  // add to sizer
110  wxPanel* mainPanel = XRCCTRL(*this, "perspective_panel", wxPanel);
111  wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL);
112  topsizer->Add(mainPanel, wxSizerFlags(1).Expand());
113  SetSizer(topsizer);
114  // remember some pointer to controls for easier access
115  m_focallengthTextCtrl = XRCCTRL(*this, "perspective_focallength", wxTextCtrl);
116  m_cropTextCtrl = XRCCTRL(*this, "perspective_cropfactor", wxTextCtrl);
117  m_previewChoice = XRCCTRL(*this, "perspective_preview", wxChoice);
118  m_zoomChoice = XRCCTRL(*this, "perspective_choice_zoom", wxChoice);
119  m_rotationChoice = XRCCTRL(*this, "perspective_rotation", wxChoice);
120  m_modeChoice = XRCCTRL(*this, "perspective_mode", wxChoice);
121  m_findLineButton = XRCCTRL(*this, "perspective_find_lines", wxButton);
122  m_helpTextCtrl = XRCCTRL(*this, "perspective_help_text", wxStaticText);
123  m_outputButton = XRCCTRL(*this, "perspective_output", wxButton);
124  m_logWindow = logWindow;
125 
126  wxConfigBase* config = wxConfigBase::Get();
127  //load and set colour
128  wxColour colour, defaultColour;
129  defaultColour.Set(HUGIN_MASK_COLOUR_POINT_SELECTED);
130  colour = config->Read("/ToolboxFrame/LineColour", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
131  XRCCTRL(*this, "perspective_color_picker", wxColourPickerCtrl)->SetColour(colour);
132  m_preview->SetLineColour(colour);
133  m_degDigits = config->Read("/General/DegreeFractionalDigitsEdit", 3);
134 
135  // bind event handler
136  Bind(wxEVT_SIZE, &PerspectivePanel::OnSize, this);
137  Bind(wxEVT_BUTTON, &PerspectivePanel::OnLoadImage, this, XRCID("perspective_load"));
138  Bind(wxEVT_BUTTON, &PerspectivePanel::OnSavePTO, this, XRCID("perspective_output_pto"));
139  m_outputButton->Bind(wxEVT_BUTTON, &PerspectivePanel::OnSaveOutput, this);
140  m_previewChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnPreview, this);
141  m_zoomChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnZoom, this);
142  m_modeChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnModeChanged, this);
143  Bind(wxEVT_CHOICE, &PerspectivePanel::OnCropChanged, this, XRCID("perspective_crop"));
144  m_rotationChoice->Bind(wxEVT_CHOICE, &PerspectivePanel::OnRotationChanged, this);
145  m_findLineButton->Bind(wxEVT_BUTTON, &PerspectivePanel::OnFindLines, this);
146  Bind(wxEVT_COLOURPICKER_CHANGED, &PerspectivePanel::OnColourChanged, this, XRCID("perspective_color_picker"));
147  // update help text
148  wxCommandEvent commandEvent;
149  OnModeChanged(commandEvent);
150  // allow dropping files
151  SetDropTarget(new PerspectiveDropTarget(this));
152  return true;
153 }
154 
155 void PerspectivePanel::OnSize(wxSizeEvent& e)
156 {
157  Layout();
158  Update();
159  Refresh();
160  e.Skip();
161 }
162 
163 void PerspectivePanel::OnZoom(wxCommandEvent& e)
164 {
165  double factor;
166  switch (e.GetSelection())
167  {
168  case 0:
169  factor = 1;
170  break;
171  case 1:
172  // fit to window
173  factor = 0;
174  break;
175  case 2:
176  factor = 2;
177  break;
178  case 3:
179  factor = 1.5;
180  break;
181  case 4:
182  factor = 0.75;
183  break;
184  case 5:
185  factor = 0.5;
186  break;
187  case 6:
188  factor = 0.25;
189  break;
190  default:
191  DEBUG_ERROR("unknown scale factor");
192  factor = 1;
193  }
194  m_preview->setScale(factor);
195 }
196 
197 void PerspectivePanel::OnPreview(wxCommandEvent& e)
198 {
199  if (m_previewChoice->GetSelection() == 1)
200  {
201  // preview mode
202  HuginBase::Panorama pano;
203  if (GetPanorama(pano))
204  {
205  // disable zoom choice in preview mode
206  m_zoomChoice->Enable(e.GetSelection() == 0);
207  m_preview->SetRemappedMode(pano);
208  }
209  else
210  {
211  // could not create pano, reset selection
212  m_previewChoice->SetSelection(0);
213  m_zoomChoice->Enable();
215  }
216  }
217  else
218  {
219  // show original
220  m_zoomChoice->Enable();
222  };
223  Refresh();
224  e.Skip();
225 }
226 
227 void PerspectivePanel::SetImage(const wxString& filename)
228 {
229  // update label for display of filename
230  XRCCTRL(*this, "perspective_filename", wxStaticText)->SetLabel(filename);
231  Layout();
232  // create HuginBase::SrcPanoImage and load values from EXIF
234  const std::string filenameString(filename.mb_str(HUGIN_CONV_FILENAME));
235  m_srcImage.setFilename(filenameString);
237  m_focallengthTextCtrl->Clear();
238  m_cropTextCtrl->Clear();
240  if (m_srcImage.readEXIF())
241  {
242  bool ok = m_srcImage.applyEXIFValues();
243  // load crop factor from database if unknown
244  if (m_srcImage.getCropFactor() < 0.1)
245  {
247  ok = (m_srcImage.getExifFocalLength() > 0 && m_srcImage.getCropFactor() > 0.1);
248  };
249  // update values in control
250  const double focallength = HuginBase::SrcPanoImage::calcFocalLength(m_srcImage.getProjection(), m_srcImage.getHFOV(), m_srcImage.getCropFactor(), m_srcImage.getSize());;
251  const double cropFactor = m_srcImage.getCropFactor();
252  if (focallength > 0 && focallength < 10000)
253  {
254  // use ChangeValue explicit, SetValue would create EVT_TEXT event which collides with our TextKillFocusHandler
256  };
257  if (cropFactor > 0 && cropFactor < 1000)
258  {
259  m_cropTextCtrl->ChangeValue(hugin_utils::doubleTowxString(cropFactor, m_degDigits));
260  };
261  const double rotation = m_srcImage.getExifOrientation();
262  if (rotation == 90)
263  {
265  }
266  else
267  {
268  if (rotation == 180)
269  {
271  }
272  else
273  {
274  if (rotation == 270)
275  {
277  };
278  };
279  };
280  };
281  m_preview->setImage(filenameString, GetRotation());
282  // reset preview mode to original
283  wxCommandEvent e;
284  m_previewChoice->SetSelection(0);
285  OnPreview(e);
286 }
287 
288 void PerspectivePanel::OnLoadImage(wxCommandEvent& e)
289 {
290  wxConfigBase* config = wxConfigBase::Get();
291  wxString path = config->Read("/actualPath", "");
292  wxFileDialog dlg(this, _("Add images"), path, wxEmptyString, GetFileDialogImageFilters(), wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_PREVIEW, wxDefaultPosition);
293  dlg.SetDirectory(path);
294 
295  // remember the image extension
296  wxString img_ext;
297  if (config->HasEntry("lastImageType"))
298  {
299  img_ext = config->Read("lastImageType").c_str();
300  }
301  if (img_ext == "all images")
302  dlg.SetFilterIndex(0);
303  else if (img_ext == "jpg")
304  dlg.SetFilterIndex(1);
305  else if (img_ext == "tiff")
306  dlg.SetFilterIndex(2);
307  else if (img_ext == "png")
308  dlg.SetFilterIndex(3);
309  else if (img_ext == "hdr")
310  dlg.SetFilterIndex(4);
311  else if (img_ext == "exr")
312  dlg.SetFilterIndex(5);
313  else if (img_ext == "all files")
314  dlg.SetFilterIndex(6);
315 
316  // call the file dialog
317  if (dlg.ShowModal() == wxID_OK)
318  {
319  // display the selected image
320  SetImage(dlg.GetPath());
321  // save the current path to config
322  config->Write("/actualPath", dlg.GetDirectory());
323  // save the image extension
324  switch (dlg.GetFilterIndex())
325  {
326  case 0: config->Write("lastImageType", "all images"); break;
327  case 1: config->Write("lastImageType", "jpg"); break;
328  case 2: config->Write("lastImageType", "tiff"); break;
329  case 3: config->Write("lastImageType", "png"); break;
330  case 4: config->Write("lastImageType", "hdr"); break;
331  case 5: config->Write("lastImageType", "exr"); break;
332  case 6: config->Write("lastImageType", "all files"); break;
333  };
334  };
335 }
336 
337 void PerspectivePanel::OnColourChanged(wxColourPickerEvent& e)
338 {
339  m_preview->SetLineColour(e.GetColour());
340  wxConfigBase::Get()->Write("/ToolboxFrame/LineColour", e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
341 }
342 
343 void PerspectivePanel::OnCropChanged(wxCommandEvent& e)
344 {
345  if (!m_preview->IsOriginalShown())
346  {
347  // refresh preview
348  OnPreview(e);
349  };
350 }
351 
352 void PerspectivePanel::OnRotationChanged(wxCommandEvent& e)
353 {
355  if (!m_preview->IsOriginalShown())
356  {
357  // refresh preview
358  OnPreview(e);
359  };
360 }
361 
362 void PerspectivePanel::OnModeChanged(wxCommandEvent& e)
363 {
364  const bool isRectMode = m_modeChoice->GetSelection() == 0;
365  m_preview->SetRectMode(isRectMode);
366  if (!m_preview->IsOriginalShown())
367  {
368  // set mode back to original
369  m_previewChoice->SetSelection(0);
370  // refresh preview
371  OnPreview(e);
372  };
373  m_findLineButton->Enable(!isRectMode);
374  m_findLineButton->Show(!isRectMode);
375  // update help text
376  m_helpTextCtrl->SetLabel(GetStatusString());
377  m_helpTextCtrl->Wrap(XRCCTRL(*this, "perspective_color_picker", wxColourPickerCtrl)->GetSize().GetWidth());
378  Layout();
379 }
380 
381 void PerspectivePanel::OnFindLines(wxCommandEvent& e)
382 {
383  HuginBase::Panorama pano;
384  // get unoptimized pano
385  if (GetPanorama(pano, false))
386  {
387  // find lines
388  HuginBase::CPVector lines;
389  if (wxGetKeyState(WXK_COMMAND))
390  {
391  lines = HuginLines::GetVerticalLines(pano, 0, *(m_preview->getCachedImage()->get8BitImage()), *(m_preview->getCachedImage()->mask), 10);
392  }
393  else
394  {
395  lines = HuginLines::GetLines(pano, 0, *(m_preview->getCachedImage()->get8BitImage()), *(m_preview->getCachedImage()->mask));
396  };
397  if (!lines.empty())
398  {
399  // add them to image control
400  m_preview->AddLines(lines);
401  // reset preview mode to original
402  m_previewChoice->SetSelection(0);
403  OnPreview(e);
404  };
405  };
406 }
407 
408 void PerspectivePanel::OnSavePTO(wxCommandEvent& e)
409 {
410  HuginBase::Panorama pano;
411  wxConfigBase* config = wxConfigBase::Get();
412  wxString path = config->Read("/actualPath", "");
413 
414  if (GetPanorama(pano))
415  {
416  wxFileDialog dlg(this, _("Save project file"), path, wxEmptyString,
417  _("Project files (*.pto)|*.pto|All files (*)|*"),
418  wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
419  if (dlg.ShowModal() == wxID_OK)
420  {
421  wxConfig::Get()->Write("/actualPath", dlg.GetDirectory()); // remember for later
422  wxString fn = dlg.GetPath();
423  if (fn.Right(4).CmpNoCase(".pto") != 0)
424  {
425  fn.Append(".pto");
426  if (wxFile::Exists(fn))
427  {
428  if (!hugin_utils::AskUserOverwrite(fn , _("Hugin toolbox"), this))
429  {
430  return;
431  };
432  };
433  };
434  const std::string script(fn.mb_str(HUGIN_CONV_FILENAME));
435  pano.WritePTOFile(script, hugin_utils::getPathPrefix(script));
436  };
437  };
438  m_preview->SendSizeEvent();
439 }
440 
441 void PerspectivePanel::OnSaveOutput(wxCommandEvent& e)
442 {
443  HuginBase::Panorama pano;
444  if (GetPanorama(pano))
445  {
446  wxConfigBase* config = wxConfigBase::Get();
447  wxString path = config->Read("/actualPath", "");
448  wxFileDialog dlg(this, _("Save output"), path, wxEmptyString, GetMainImageFilters(), wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
449  dlg.SetDirectory(path);
450 
451  // remember the image extension
452  wxString img_ext;
453  if (config->HasEntry("lastImageType"))
454  {
455  img_ext = config->Read("lastImageType").c_str();
456  };
457  if (img_ext == "jpg")
458  {
459  dlg.SetFilterIndex(0);
460  }
461  else
462  {
463  if (img_ext == "tiff")
464  {
465  dlg.SetFilterIndex(1);
466  }
467  else
468  {
469  if (img_ext == "png")
470  {
471  dlg.SetFilterIndex(2);
472  };
473  };
474  };
475  wxFileName outputfilename(wxString(m_srcImage.getFilename().c_str(), HUGIN_CONV_FILENAME));
476  wxString inputFilename = outputfilename.GetFullPath();
477  outputfilename.SetName(outputfilename.GetName() + "_corrected");
478  dlg.SetFilename(outputfilename.GetFullPath());
479  // call the file dialog
480  if (dlg.ShowModal() == wxID_OK)
481  {
482  std::string outputFilename(dlg.GetPath().mb_str(HUGIN_CONV_FILENAME));
483  // save the current path to config
484  config->Write("/actualPath", dlg.GetDirectory());
485  // save the image extension
486  wxString tempFilename = wxFileName::CreateTempFileName(HuginQueue::GetConfigTempDir(wxConfig::Get()) + "htb");
487  pano.WritePTOFile(std::string(tempFilename.mb_str(HUGIN_CONV_FILENAME)));
488  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
489  wxString nonaArgs;
490  switch (dlg.GetFilterIndex())
491  {
492  case 0:
493  config->Write("lastImageType", "jpg");
494  nonaArgs.Append("-m JPEG ");
495  break;
496  case 1:
497  default:
498  config->Write("lastImageType", "tiff");
499  nonaArgs.Append("-m TIFF ");
500  break;
501  case 2:
502  config->Write("lastImageType", "png");
503  nonaArgs.Append("-m PNG ");
504  break;
505  };
506  // use nona for remapping
507  nonaArgs.Append("-v -o " + HuginQueue::wxEscapeFilename(dlg.GetPath()) + " " + HuginQueue::wxEscapeFilename(tempFilename));
509  queue->push_back(new HuginQueue::NormalCommand(HuginQueue::GetInternalProgram(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), "nona"), nonaArgs, _("Remapping image")));
510  wxString exiftoolArgs("-overwrite_original -tagsfromfile ");
511  exiftoolArgs.Append(HuginQueue::wxEscapeFilename(wxString(m_srcImage.getFilename().c_str(), HUGIN_CONV_FILENAME)));
512  // tags to copy and to ignore (white space at begin and at end!)
513  exiftoolArgs.Append(" -all:all --thumbnail --xposition --yposition --orientation --imagefullwidth --imagefullheight ");
514  exiftoolArgs.Append(HuginQueue::wxEscapeFilename(dlg.GetPath()));
515  queue->push_back(new HuginQueue::OptionalCommand(HuginQueue::GetExternalProgram(wxConfig::Get(), exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR), "exiftool"), exiftoolArgs, _("Updating EXIF")));
516  m_tempFiles.Add(tempFilename);
518  m_logWindow->ExecQueue(queue);
519  m_outputButton->Disable();
520  };
521  };
522 }
523 
524 void PerspectivePanel::OnProcessFinished(wxCommandEvent& e)
525 {
526  if (!m_tempFiles.IsEmpty())
527  {
528  // delete all temporary files at the end of command
529  for (auto& file : m_tempFiles)
530  {
531  if (wxFileExists(file))
532  {
533  wxRemoveFile(file);
534  };
535  };
536  m_tempFiles.clear();
537  };
538  m_outputButton->Enable();
539 }
540 
542 {
543  if (m_modeChoice->GetSelection()==0)
544  {
545  return _("Adjust the rectangle to an area which should be rectangular in the projected image.");
546  }
547  else
548  {
549  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.");
550  };
551 }
552 
554 {
555  if (m_srcImage.getFilename().empty())
556  {
557  hugin_utils::HuginMessageBox(_("You need to load an image first."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
558  return false;
559  }
560  wxString focallengthText = m_focallengthTextCtrl->GetValue();
561  if (focallengthText.IsEmpty())
562  {
563  hugin_utils::HuginMessageBox(_("Focal length input box is empty."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
564  return false;
565  };
566  double focallength, cropfactor;
567  if (!hugin_utils::str2double(focallengthText, focallength))
568  {
569  hugin_utils::HuginMessageBox(_("Focal length input box contains no valid number."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
570  return false;
571  }
572  //no negative values, no zero input please
573  if (focallength < 0.1)
574  {
575  hugin_utils::HuginMessageBox(_("The focal length must be positive."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
576  return false;
577  };
578  wxString cropfactorText = m_cropTextCtrl->GetValue();
579  if (cropfactorText.IsEmpty())
580  {
581  hugin_utils::HuginMessageBox(_("Crop factor input box is empty."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
582  return false;
583  };
584  if (!hugin_utils::str2double(cropfactorText, cropfactor))
585  {
586  hugin_utils::HuginMessageBox(_("Crop factor input box contains no valid number."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
587  return false;
588  }
589  //no negative values, no zero input please
590  if (cropfactor < 0.1)
591  {
592  hugin_utils::HuginMessageBox(_("The crop factor must be positive."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
593  return false;
594  };
595  const double hfov = HuginBase::SrcPanoImage::calcHFOV(m_srcImage.getProjection(), focallength, cropfactor, m_srcImage.getSize());
596  if (hfov > 178)
597  {
598  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."),
599  _("Hugin toolbox"), wxICON_QUESTION | wxOK, this);
600  return false;
601  };
602  m_srcImage.setHFOV(hfov);
603  return true;
604 }
605 
606 bool PerspectivePanel::GetPanorama(HuginBase::Panorama& pano, const bool optimized)
607 {
608  if (ReadInputs())
609  {
611  panoImage.setRoll(GetRoll());
612  pano.addImage(panoImage);
614  if (optimized && pano.getCtrlPoints().size() < 2)
615  {
616  hugin_utils::HuginMessageBox(_("You need to create at least 2 lines."), _("Hugin toolbox"), wxICON_ERROR | wxOK, this);
617  return false;
618  };
620  // optimize yaw, pitch and roll
621  std::set<std::string> imgopt;
622  imgopt.insert("y");
623  imgopt.insert("p");
624  imgopt.insert("r");
625  optvec.push_back(imgopt);
626  pano.setOptimizeVector(optvec);
627  // set some sensible values for PanoramaOptions
630  opts.outputExposureValue = m_srcImage.getExposureValue();
631  pano.setOptions(opts);
632  // now optimize pano
633  if (optimized)
634  {
638  // calculate field of view
639  HuginBase::CalculateFitPanorama fitPano(pano);
640  fitPano.run();
641  opts.setHFOV(fitPano.getResultHorizontalFOV());
643  // calculate scale
645  opts.setWidth(scale * opts.getWidth());
646  pano.setOptions(opts);
647  // crop pano
649  const int cropMode = XRCCTRL(*this, "perspective_crop", wxChoice)->GetSelection();
650  if (cropMode == 1)
651  {
652  // crop inside
653  HuginBase::CalculateOptimalROI cropPano(pano, &progress);
654  cropPano.run();
655  if (cropPano.hasRunSuccessfully())
656  {
657  opts.setROI(cropPano.getResultOptimalROI());
658  };
659  pano.setOptions(opts);
660  }
661  else
662  {
663  // crop outside
664  HuginBase::CalculateOptimalROIOutside cropPano(pano, &progress);
665  cropPano.run();
666  if (cropPano.hasRunSuccessfully())
667  {
668  opts.setROI(cropPano.getResultOptimalROI());
669  };
670  pano.setOptions(opts);
671  };
672  };
673  return true;
674  }
675  else
676  {
677  return false;
678  };
679 }
680 
682 {
683  switch (m_rotationChoice->GetSelection())
684  {
685  case 0:
686  default:
687  // auto-rotate, return EXIF value
688  return m_exifRotation;
689  break;
690  case 1:
692  break;
693  case 2:
695  break;
696  case 3:
698  break;
699  case 4:
701  break;
702  }
704 }
705 
706 const double PerspectivePanel::GetRoll() const
707 {
708  switch (GetRotation())
709  {
711  default:
712  return 0.0;
713  break;
715  return 90.0;
716  break;
718  return 180.0;
719  break;
721  return 270.0;
722  break;
723  }
724  return 0.0;
725 }
726 
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 OnSize(wxSizeEvent &e)
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
~PerspectivePanel()
destructor, save position and size
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:80
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:69
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