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