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