Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PanoPanel.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
28 #include "hugin_config.h"
29 #include <wx/stdpaths.h>
30 
31 #include "panoinc_WX.h"
32 #include "panoinc.h"
33 #include "base_wx/platform.h"
34 #include "base_wx/PanoCommand.h"
35 #include "base_wx/wxutils.h"
36 
37 #include <hugin/config_defaults.h>
38 
39 #include "nona/Stitcher.h"
40 #include "base_wx/wxPlatform.h"
41 
42 extern "C" {
43 #include <pano13/queryfeature.h>
44 }
45 
46 #include "base_wx/CommandHistory.h"
47 #include "hugin/CPImageCtrl.h"
48 #include "hugin/CPImagesComboBox.h"
49 #include "hugin/PanoPanel.h"
50 #include "hugin/MainFrame.h"
51 #include "hugin/huginApp.h"
55 #include "hugin/config_defaults.h"
56 #include "base_wx/platform.h"
57 #include "base_wx/huginConfig.h"
58 #include "base_wx/LensTools.h"
63 #include "lensdb/LensDB.h"
64 #include "hugin_math/hugin_math.h"
65 
67  : pano(0), m_guiLevel(GUI_SIMPLE), updatesDisabled(false)
68 {
69 
70 }
71 
72 bool PanoPanel::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
73  long style, const wxString& name)
74 {
75  if (! wxPanel::Create(parent, id, pos, size, style, name)) {
76  return false;
77  }
78 
79  wxXmlResource::Get()->LoadPanel(this, "panorama_panel");
80  wxPanel * panel = XRCCTRL(*this, "panorama_panel", wxPanel);
81 
82  wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
83  topsizer->Add(panel, 1, wxEXPAND, 0);
84  SetSizer(topsizer);
85 
86  // converts KILL_FOCUS events to usable TEXT_ENTER events
87  // get gui controls
88  m_ProjectionChoice = XRCCTRL(*this, "pano_choice_pano_type" ,wxChoice);
89  m_ProjectionChoice->Bind(wxEVT_CHOICE, &PanoPanel::ProjectionChanged, this);
91 
92  m_keepViewOnResize = true;
93  m_hasStacks=false;
94 
95 #ifdef ThisNeverHappens
96 // provide some translatable strings for the drop down menu
97  wxLogMessage(_("Fisheye"));
98  wxLogMessage(_("Stereographic"));
99  wxLogMessage(_("Mercator"));
100  wxLogMessage(_("Trans Mercator"));
101  wxLogMessage(_("Sinusoidal"));
102  wxLogMessage(_("Lambert Cylindrical Equal Area"));
103  wxLogMessage(_("Lambert Equal Area Azimuthal"));
104  wxLogMessage(_("Albers Equal Area Conic"));
105  wxLogMessage(_("Miller Cylindrical"));
106  wxLogMessage(_("Panini"));
107  wxLogMessage(_("Architectural"));
108  wxLogMessage(_("Orthographic"));
109  wxLogMessage(_("Equisolid"));
110  wxLogMessage(_("Equirectangular Panini"));
111  wxLogMessage(_("Biplane"));
112  wxLogMessage(_("Triplane"));
113  wxLogMessage(_("Panini General"));
114  wxLogMessage(_("Thoby Projection"));
115  wxLogMessage(_("Hammer-Aitoff Equal Area"));
116 #endif
117 
118  /* populate with all available projection types */
119  int nP = panoProjectionFormatCount();
120  for(int n=0; n < nP; n++) {
121  pano_projection_features proj;
122  if (panoProjectionFeaturesQuery(n, &proj)) {
123  wxString str2(proj.name, wxConvLocal);
124  m_ProjectionChoice->Append(wxGetTranslation(str2));
125  }
126  }
127  m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
129  m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
130  m_HFOVText->Bind(wxEVT_TEXT_ENTER, &PanoPanel::HFOVChanged, this);
131  m_CalcHFOVButton = XRCCTRL(*this, "pano_button_calc_fov" ,wxButton);
133  m_CalcHFOVButton->Bind(wxEVT_BUTTON, &PanoPanel::DoCalcFOV, this);
134  m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
136  m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
137  m_VFOVText->Bind(wxEVT_TEXT_ENTER, &PanoPanel::VFOVChanged, this);
138 
139 
140  m_WidthTxt = XRCCTRL(*this, "pano_val_width", wxTextCtrl);
142  m_WidthTxt->PushEventHandler(new TextKillFocusHandler(this));
143  m_WidthTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::WidthChanged, this);
144 
145  m_CalcOptWidthButton = XRCCTRL(*this, "pano_button_opt_width" ,wxButton);
147  m_CalcOptWidthButton->Bind(wxEVT_BUTTON, &PanoPanel::DoCalcOptimalWidth, this);
148 
149  m_HeightTxt = XRCCTRL(*this, "pano_val_height", wxTextCtrl);
151  m_HeightTxt->PushEventHandler(new TextKillFocusHandler(this));
152  m_HeightTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::HeightChanged, this);
153 
154 
155  m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
157  m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
158  m_ROILeftTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::ROIChanged, this);
159 
160 
161  m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
163  m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
164  m_ROIRightTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::ROIChanged, this);
165 
166  m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
168  m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
169  m_ROITopTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::ROIChanged, this);
170 
171 
172  m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
174  m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
175  m_ROIBottomTxt->Bind(wxEVT_TEXT_ENTER, &PanoPanel::ROIChanged, this);
176 
177  m_CalcOptROIButton = XRCCTRL(*this, "pano_button_opt_roi" ,wxButton);
179  m_CalcOptROIButton->Bind(wxEVT_BUTTON, &PanoPanel::DoCalcOptimalROI, this);
180 
181  m_RemapperChoice = XRCCTRL(*this, "pano_choice_remapper", wxChoice);
183  m_RemapperChoice->Bind(wxEVT_CHOICE, &PanoPanel::RemapperChanged, this);
184  m_FusionChoice = XRCCTRL(*this, "pano_choice_fusion", wxChoice);
186  m_FusionChoice->Bind(wxEVT_CHOICE, &PanoPanel::FusionChanged, this);
187  m_HDRMergeChoice = XRCCTRL(*this, "pano_choice_hdrmerge", wxChoice);
189  m_HDRMergeChoice->Bind(wxEVT_CHOICE, &PanoPanel::HDRMergeChanged, this);
190  m_BlenderChoice = XRCCTRL(*this, "pano_choice_blender", wxChoice);
193  m_BlenderChoice->Bind(wxEVT_CHOICE, &PanoPanel::BlenderChanged, this);
194  m_edgeFillChoice = XRCCTRL(*this, "pano_choice_edgefill", wxChoice);
195  m_edgeFillChoice->Bind(wxEVT_CHOICE, &PanoPanel::OnEdgeFillChanged, this);
196 
197  m_StitchButton = XRCCTRL(*this, "pano_button_stitch", wxButton);
199  m_StitchButton->Bind(wxEVT_BUTTON, &PanoPanel::OnDoStitch, this);
200 
201  m_FileFormatChoice = XRCCTRL(*this, "pano_choice_file_format", wxChoice);
203  m_FileFormatChoice->Bind(wxEVT_CHOICE, &PanoPanel::FileFormatChanged, this);
204  m_FileFormatOptionsLabel = XRCCTRL(*this, "pano_output_ldr_format_options_label", wxStaticText);
205 
206  m_FileFormatJPEGQualityText = XRCCTRL(*this, "pano_output_normal_opts_jpeg_quality", wxTextCtrl);
208  m_FileFormatJPEGQualityText->PushEventHandler(new TextKillFocusHandler(this));
209  m_FileFormatJPEGQualityText->Bind(wxEVT_TEXT_ENTER, &PanoPanel::OnJPEGQualityText, this);
210 
211  m_FileFormatTIFFCompChoice = XRCCTRL(*this, "pano_output_normal_opts_tiff_compression", wxChoice);
214 
215  m_HDRFileFormatChoice = XRCCTRL(*this, "pano_choice_hdr_file_format", wxChoice);
217  m_HDRFileFormatChoice->Bind(wxEVT_CHOICE, &PanoPanel::HDRFileFormatChanged, this);
218  m_HDRFileFormatLabelTIFFCompression = XRCCTRL(*this, "pano_output_hdr_opts_tiff_compression_label", wxStaticText);
220  m_FileFormatHDRTIFFCompChoice = XRCCTRL(*this, "pano_output_hdr_opts_tiff_compression", wxChoice);
223 
224  m_pano_ctrls = XRCCTRL(*this, "pano_controls_panel", wxScrolledWindow);
226  m_pano_ctrls->SetSizeHints(20, 20);
227  m_pano_ctrls->FitInside();
228  m_pano_ctrls->SetScrollRate(10, 10);
229  // bind event handler for buttons
230  Bind(wxEVT_BUTTON, &PanoPanel::OnRemapperOptions, this, XRCID("pano_button_remapper_opts"));
231  Bind(wxEVT_BUTTON, &PanoPanel::OnFusionOptions, this, XRCID("pano_button_fusion_opts"));
232  Bind(wxEVT_BUTTON, &PanoPanel::OnHDRMergeOptions, this, XRCID("pano_button_hdrmerge_opts"));
233  Bind(wxEVT_BUTTON, &PanoPanel::OnBlenderOptions, this, XRCID("pano_button_blender_opts"));
234  Bind(wxEVT_BUTTON, &PanoPanel::OnEdgeFillOptions, this, XRCID("pano_button_fill_opts"));
235  // bind event handler for checkboxes
236  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_blended"));
237  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_layers"));
238  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_exposure_layers"));
239  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_exposure_blended"));
240  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_exposure_layers_fused"));
241  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_stacks"));
242  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_ldr_output_exposure_remapped"));
243  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_hdr_output_blended"));
244  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_hdr_output_stacks"));
245  Bind(wxEVT_CHECKBOX, &PanoPanel::OnOutputFilesChanged, this, XRCID("pano_cb_hdr_output_layers"));
246 
247  return true;
248 }
249 
251 {
252  pano = panorama;
253  // observe the panorama
254  pano->addObserver(this);
255  panoramaChanged(*panorama);
256 }
257 
259 {
260  DEBUG_TRACE("dtor");
261  wxConfigBase::Get()->Write("Stitcher/DefaultRemapper",m_RemapperChoice->GetSelection());
262  wxConfigBase::Get()->Flush();
263 
264  m_HFOVText->PopEventHandler(true);
265  m_VFOVText->PopEventHandler(true);
266  m_WidthTxt->PopEventHandler(true);
267  m_HeightTxt->PopEventHandler(true);
268  m_ROILeftTxt->PopEventHandler(true);
269  m_ROIRightTxt->PopEventHandler(true);
270  m_ROITopTxt->PopEventHandler(true);
271  m_ROIBottomTxt->PopEventHandler(true);
272  m_FileFormatJPEGQualityText->PopEventHandler(true);
273  pano->removeObserver(this);
274  DEBUG_TRACE("dtor end");
275 }
276 
277 
279 {
280  DEBUG_TRACE("");
281 
282 #ifdef STACK_CHECK //Disabled for 0.7.0 release
283  const bool hasStacks = StackCheck(pano);
284 #else
285  const bool hasStacks = false;
286 #endif
287 
289 
290  // update all options for dialog and notebook tab
291  UpdateDisplay(opt,hasStacks);
292 
293  m_oldOpt = opt;
294 }
295 
296 
298 {
299  DEBUG_TRACE("");
301 
302  // Determine if there are stacks in the pano.
303  HuginBase::UIntSet activeImages = pano.getActiveImages();
304  HuginBase::UIntSet images = getImagesinROI(pano, activeImages);
305  std::vector<HuginBase::UIntSet> hdrStacks = HuginBase::getHDRStacks(pano, images, pano.getOptions());
306  DEBUG_DEBUG(hdrStacks.size() << ": HDR stacks detected");
307  const bool hasStacks = (hdrStacks.size() != activeImages.size());
308 
309  // Only change the output types if the stack configuration has changed.
310  bool isChanged = (hasStacks != m_hasStacks);
311  if (isChanged) {
312  if (hasStacks) {
313  // Disable normal output formats
314  opt.outputLDRBlended = false;
315  opt.outputLDRLayers = false;
316  // Ensure at least one fused output is enabled
317  if (!(opt.outputLDRExposureBlended ||
320  opt.outputHDRBlended ||
321  opt.outputHDRStacks ||
322  opt.outputHDRLayers)) {
323  opt.outputLDRExposureBlended = true;
324  }
325  } else {
326  // Disable fused output formats
327  opt.outputLDRExposureBlended = false;
328  opt.outputLDRExposureLayers = false;
329  opt.outputLDRExposureRemapped = false;
330  opt.outputHDRBlended = false;
331  opt.outputHDRStacks = false;
332  opt.outputHDRLayers = false;
333  // Ensure at least one normal output is enabled
334  if (!(opt.outputLDRBlended || opt.outputLDRLayers)) {
335  opt.outputLDRBlended = true;
336  }
337  }
338  pano.setOptions(opt);
339  }
340 
341  m_hasStacks = hasStacks;
342 
343  return hasStacks;
344 }
345 
346 
347 void PanoPanel::UpdateDisplay(const HuginBase::PanoramaOptions & opt, const bool hasStacks)
348 {
349  Freeze();
350 // m_HFOVSpin->SetRange(1,opt.getMaxHFOV());
351 // m_VFOVSpin->SetRange(1,opt.getMaxVFOV());
352 
353  m_ProjectionChoice->SetSelection(opt.getProjection());
355 
356  std::string val;
357  val = hugin_utils::doubleToString(opt.getHFOV(),1);
358  m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
359  val = hugin_utils::doubleToString(opt.getVFOV(), 1);
360  m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
361 
362  // disable VFOV edit field, due to bugs in setHeight(), setWidth()
363  const bool hasImages = !pano->getActiveImages().empty();
365  m_CalcOptWidthButton->Enable(m_keepViewOnResize && hasImages);
366  m_CalcHFOVButton->Enable(m_keepViewOnResize && hasImages);
367  m_CalcOptROIButton->Enable(hasImages);
368 
369  m_WidthTxt->ChangeValue(wxString::Format("%d", opt.getWidth()));
370  m_HeightTxt->ChangeValue(wxString::Format("%d", opt.getHeight()));
371 
372  m_ROILeftTxt->ChangeValue(wxString::Format("%d", opt.getROI().left() ));
373  m_ROIRightTxt->ChangeValue(wxString::Format("%d", opt.getROI().right() ));
374  m_ROITopTxt->ChangeValue(wxString::Format("%d", opt.getROI().top() ));
375  m_ROIBottomTxt->ChangeValue(wxString::Format("%d", opt.getROI().bottom() ));
376  {
377  // format text for display of canvas dimension
378  wxString label = wxString::Format("%d x %d", opt.getROI().width(), opt.getROI().height());
379  // using opt.getROI().area() can overflow, so use width and height explicit to prevent this
380  if ( (opt.getROI().width() / 1000.0) * opt.getROI().height() / 1000.0 >= 20.0)
381  {
382  label.Append(wxString::Format("=%.0f MP", (opt.getROI().width() / 1000.0) * opt.getROI().height() / 1000.0));
383  }
384  else
385  {
386  label.Append(wxString::Format("=%.1f MP", opt.getROI().area() / 1000000.0));
387  };
388  if (opt.getROI().width() >0 && opt.getROI().height() > 0)
389  {
390  const int commonDivisor = hugin_utils::gcd(opt.getROI().width(), opt.getROI().height());
391  if (commonDivisor > std::pow(10, hugin_utils::floori(log10f(std::max(opt.getROI().width(), opt.getROI().height()))) - 2))
392  {
393  label.Append(wxString::Format(", %d:%d", opt.getROI().width() / commonDivisor, opt.getROI().height() / commonDivisor));
394  }
395  else
396  {
397  float ratio = 1.0f * opt.getROI().width() / opt.getROI().height();
398  if (ratio > 1.0f)
399  {
400  label.Append(wxString::Format(", %.2f:1", ratio));
401  }
402  else
403  {
404  label.Append(wxString::Format(", 1:%.2f", 1.0f/ratio));
405  };
406  };
407  };
408  XRCCTRL(*this, "pano_size_label", wxStaticText)->SetLabel(label);
409  };
410 
411  // output types
412  XRCCTRL(*this, "pano_cb_ldr_output_blended", wxCheckBox)->SetValue(opt.outputLDRBlended);
413  XRCCTRL(*this, "pano_cb_ldr_output_exposure_blended", wxCheckBox)->SetValue(opt.outputLDRExposureBlended);
414  XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers_fused", wxCheckBox)->SetValue(opt.outputLDRExposureLayersFused);
415  XRCCTRL(*this, "pano_cb_hdr_output_blended", wxCheckBox)->SetValue(opt.outputHDRBlended);
416  XRCCTRL(*this, "pano_cb_hdr_output_blended", wxCheckBox)->Show(opt.outputHDRBlended || m_guiLevel>GUI_SIMPLE);
417 
418  //remapped images
419  XRCCTRL(*this, "pano_text_remapped_images", wxStaticText)->Show(opt.outputLDRLayers || opt.outputLDRExposureRemapped || opt.outputHDRLayers || m_guiLevel>GUI_SIMPLE);
420  XRCCTRL(*this, "pano_cb_ldr_output_layers", wxCheckBox)->SetValue(opt.outputLDRLayers);
421  XRCCTRL(*this, "pano_cb_ldr_output_layers", wxCheckBox)->Show(opt.outputLDRLayers || m_guiLevel>GUI_SIMPLE);
422  XRCCTRL(*this, "pano_cb_ldr_output_exposure_remapped", wxCheckBox)->SetValue(opt.outputLDRExposureRemapped);
423  XRCCTRL(*this, "pano_cb_ldr_output_exposure_remapped", wxCheckBox)->Show(opt.outputLDRExposureRemapped || m_guiLevel>GUI_SIMPLE);
424  XRCCTRL(*this, "pano_cb_hdr_output_layers", wxCheckBox)->SetValue(opt.outputHDRLayers);
425  XRCCTRL(*this, "pano_cb_hdr_output_layers", wxCheckBox)->Show(opt.outputHDRLayers || m_guiLevel>GUI_SIMPLE);
426 
427  //stacks
428  XRCCTRL(*this, "pano_text_stacks", wxStaticText)->Show(opt.outputHDRStacks || opt.outputLDRStacks || m_guiLevel>GUI_SIMPLE);
429  XRCCTRL(*this, "pano_cb_ldr_output_stacks", wxCheckBox)->SetValue(opt.outputLDRStacks);
430  XRCCTRL(*this, "pano_cb_ldr_output_stacks", wxCheckBox)->Show(opt.outputLDRStacks || m_guiLevel>GUI_SIMPLE);
431  XRCCTRL(*this, "pano_cb_hdr_output_stacks", wxCheckBox)->SetValue(opt.outputHDRStacks);
432  XRCCTRL(*this, "pano_cb_hdr_output_stacks", wxCheckBox)->Show(opt.outputHDRStacks || m_guiLevel>GUI_SIMPLE);
433 
434  //layers
435  XRCCTRL(*this, "pano_text_layers", wxStaticText)->Show(opt.outputLDRExposureLayers || m_guiLevel>GUI_SIMPLE);
436  XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers", wxCheckBox)->SetValue(opt.outputLDRExposureLayers);
437  XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers", wxCheckBox)->Show(opt.outputLDRExposureLayers || m_guiLevel>GUI_SIMPLE);
438 
439  bool anyOutputSelected = (opt.outputLDRBlended ||
440  opt.outputLDRLayers ||
445  opt.outputLDRStacks ||
446  opt.outputHDRBlended ||
447  opt.outputHDRStacks ||
448  opt.outputHDRLayers);
449 
450  //do not let the user stitch unless there are active images and an output selected.
451  bool any_output_possible = hasImages && anyOutputSelected;
452  m_StitchButton->Enable(any_output_possible);
453 
454 #ifdef STACK_CHECK //Disabled for 0.7.0 release
455  if (hasStacks) {
456  XRCCTRL(*this,"pano_cb_ldr_output_blended",wxCheckBox)->Disable();
457  XRCCTRL(*this,"pano_cb_ldr_output_layers",wxCheckBox)->Disable();
458 
459  XRCCTRL(*this,"pano_cb_ldr_output_exposure_layers",wxCheckBox)->Enable();
460  XRCCTRL(*this,"pano_cb_ldr_output_exposure_blended",wxCheckBox)->Enable();
461  XRCCTRL(*this,"pano_cb_ldr_output_exposure_remapped",wxCheckBox)->Enable();
462  XRCCTRL(*this,"pano_cb_hdr_output_blended",wxCheckBox)->Enable();
463  XRCCTRL(*this,"pano_cb_hdr_output_stacks",wxCheckBox)->Enable();
464  XRCCTRL(*this,"pano_cb_hdr_output_layers",wxCheckBox)->Enable();
465 
466  } else {
467  XRCCTRL(*this,"pano_cb_ldr_output_blended",wxCheckBox)->Enable();
468  XRCCTRL(*this,"pano_cb_ldr_output_layers",wxCheckBox)->Enable();
469 
470  XRCCTRL(*this,"pano_cb_ldr_output_exposure_layers",wxCheckBox)->Disable();
471  XRCCTRL(*this,"pano_cb_ldr_output_exposure_blended",wxCheckBox)->Disable();
472  XRCCTRL(*this,"pano_cb_ldr_output_exposure_remapped",wxCheckBox)->Disable();
473 
474  XRCCTRL(*this,"pano_cb_hdr_output_blended",wxCheckBox)->Disable();
475  XRCCTRL(*this,"pano_cb_hdr_output_stacks",wxCheckBox)->Disable();
476  XRCCTRL(*this,"pano_cb_hdr_output_layers",wxCheckBox)->Disable();
477  }
478 #endif
479 
482  XRCCTRL(*this, "pano_button_remapper_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
483  XRCCTRL(*this, "pano_button_remapper_opts", wxButton)->Enable(m_guiLevel>GUI_SIMPLE);
484  XRCCTRL(*this, "pano_text_remapper", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
485  XRCCTRL(*this, "pano_text_processing", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
486 
487  bool blenderEnabled = (opt.outputLDRBlended ||
492 
493  m_BlenderChoice->Enable(blenderEnabled);
495  // select correct blending mechanism
497  XRCCTRL(*this, "pano_button_blender_opts", wxButton)->Enable(blenderEnabled);
498  XRCCTRL(*this, "pano_button_blender_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
499  XRCCTRL(*this, "pano_text_blender", wxStaticText)->Enable(blenderEnabled);
500  XRCCTRL(*this, "pano_text_blender", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
501  m_edgeFillChoice->SetSelection(static_cast<int>(opt.edgeFillMode));
502  XRCCTRL(*this, "pano_button_fill_opts", wxButton)->Enable(m_edgeFillChoice->GetSelection() != 0);
503 
505  m_FusionChoice->Enable(fusionEnabled);
507  XRCCTRL(*this, "pano_button_fusion_opts", wxButton)->Enable(fusionEnabled);
508  XRCCTRL(*this, "pano_button_fusion_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
509  XRCCTRL(*this, "pano_text_fusion", wxStaticText)->Enable(fusionEnabled);
510  XRCCTRL(*this, "pano_text_fusion", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
511 
512  bool hdrMergeEnabled = (opt.outputHDRBlended || opt.outputHDRStacks) && m_guiLevel>GUI_SIMPLE;
513  m_HDRMergeChoice->Enable(hdrMergeEnabled);
515  XRCCTRL(*this, "pano_button_hdrmerge_opts", wxButton)->Enable(hdrMergeEnabled);
516  XRCCTRL(*this, "pano_button_hdrmerge_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
517  XRCCTRL(*this, "pano_text_hdrmerge", wxStaticText)->Enable(hdrMergeEnabled);
518  XRCCTRL(*this, "pano_text_hdrmerge", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
519 
522  XRCCTRL(*this, "pano_button_fill_opts", wxButton)->Enable(m_guiLevel > GUI_SIMPLE);
523  XRCCTRL(*this, "pano_button_fill_opts", wxButton)->Show(m_guiLevel > GUI_SIMPLE);
524  XRCCTRL(*this, "pano_text_edgefill", wxStaticText)->Enable(m_guiLevel > GUI_SIMPLE);
525  XRCCTRL(*this, "pano_text_edgefill", wxStaticText)->Show(m_guiLevel > GUI_SIMPLE);
526 
527  // output file mode
528  bool ldr_pano_enabled = opt.outputLDRBlended ||
531 
532  XRCCTRL(*this, "pano_output_ldr_format_label", wxStaticText)->Enable(ldr_pano_enabled);
533  m_FileFormatOptionsLabel->Enable(ldr_pano_enabled);
534  m_FileFormatChoice->Enable(ldr_pano_enabled);
535  m_FileFormatJPEGQualityText->Enable(ldr_pano_enabled);
536  m_FileFormatTIFFCompChoice->Enable(ldr_pano_enabled);
537 
538  long i=0;
539  if (opt.outputImageType == "tif") {
540  i = 0;
541  m_FileFormatOptionsLabel->Show();
542  m_FileFormatOptionsLabel->SetLabel(_("Compression:"));
545  if (opt.outputImageTypeCompression == "PACKBITS") {
546  m_FileFormatTIFFCompChoice->SetSelection(1);
547  } else if (opt.outputImageTypeCompression == "LZW") {
548  m_FileFormatTIFFCompChoice->SetSelection(2);
549  } else if (opt.outputImageTypeCompression == "DEFLATE") {
550  m_FileFormatTIFFCompChoice->SetSelection(3);
551  } else {
552  m_FileFormatTIFFCompChoice->SetSelection(0);
553  }
554  } else if (opt.outputImageType == "jpg") {
555  i = 1;
556  m_FileFormatOptionsLabel->Show();
557  m_FileFormatOptionsLabel->SetLabel(_("Quality:"));
560  m_FileFormatJPEGQualityText->ChangeValue(wxString::Format("%d", opt.quality));
561  } else if (opt.outputImageType == "png") {
562  m_FileFormatOptionsLabel->Hide();
565  i = 2;
566  } else if (opt.outputImageType == "exr") {
568  m_FileFormatOptionsLabel->Hide();
571  i = 3;
572  } else
573  wxLogError("INTERNAL error: unknown output image type");
574 
575  m_FileFormatChoice->SetSelection(i);
576 
577  bool hdr_pano_enabled = opt.outputHDRBlended;
578 
579  XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Enable(hdr_pano_enabled);
580  XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
581  m_HDRFileFormatChoice->Enable(hdr_pano_enabled);
582  m_HDRFileFormatChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
583  m_HDRFileFormatLabelTIFFCompression->Enable(hdr_pano_enabled);
584  m_HDRFileFormatLabelTIFFCompression->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
585  m_FileFormatHDRTIFFCompChoice->Enable(hdr_pano_enabled);
586  m_FileFormatHDRTIFFCompChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
587 
588  i=0;
589  if (opt.outputImageTypeHDR == "exr") {
590  i = 0;
593  } else if (opt.outputImageTypeHDR == "tif") {
594  i = 1;
597  if (opt.outputImageTypeHDRCompression == "PACKBITS") {
598  m_FileFormatHDRTIFFCompChoice->SetSelection(1);
599  } else if (opt.outputImageTypeHDRCompression == "LZW") {
600  m_FileFormatHDRTIFFCompChoice->SetSelection(2);
601  } else if (opt.outputImageTypeHDRCompression == "DEFLATE") {
602  m_FileFormatHDRTIFFCompChoice->SetSelection(3);
603  } else {
604  m_FileFormatHDRTIFFCompChoice->SetSelection(0);
605  }
606  } else
607  wxLogError("INTERNAL error: unknown hdr output image type");
608 
609  m_HDRFileFormatChoice->SetSelection(i);
610 
611  m_pano_ctrls->FitInside();
612  Layout();
613  Thaw();
614 
615 #ifdef __WXMSW__
616  this->Refresh(false);
617 #endif
618 }
619 
620 void PanoPanel::ProjectionChanged ( wxCommandEvent & e )
621 {
622  if (updatesDisabled) return;
624 // PanoramaOptions::ProjectionFormat oldP = opt.getProjection();
625 
627 // int w = opt.getWidth();
628 // int h = opt.getHeight();
629  opt.setProjection(newP);
630 
633  );
634  DEBUG_DEBUG ("Projection changed: " << newP)
635 }
636 
637 void PanoPanel::HFOVChanged ( wxCommandEvent & e )
638 {
639  if (updatesDisabled) return;
641 
642 
643  wxString text = m_HFOVText->GetValue();
644  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
645  if (text == wxEmptyString) {
646  return;
647  }
648 
649  double hfov;
650  if (!hugin_utils::str2double(text, hfov)) {
651  wxLogError(_("Value must be numeric."));
652  return;
653  }
654 
655  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
656  wxLogError(wxString::Format(
657  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
658  opt.getMaxHFOV()));
659  }
660  opt.setHFOV(hfov);
661  // recalculate panorama height...
664  );
665 
666  DEBUG_INFO ( "new hfov: " << hfov )
667 }
668 
669 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
670 {
671  if (updatesDisabled) return;
673 
674  wxString text = m_VFOVText->GetValue();
675  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
676  if (text == wxEmptyString) {
677  return;
678  }
679 
680  double vfov;
681  if (!hugin_utils::str2double(text, vfov)) {
682  wxLogError(_("Value must be numeric."));
683  return;
684  }
685 
686  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
687  wxLogError(wxString::Format(
688  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
689  opt.getMaxVFOV()));
690  vfov = opt.getMaxVFOV();
691  }
692  opt.setVFOV(vfov);
693  // recalculate panorama height...
696  );
697 
698  DEBUG_INFO ( "new vfov: " << vfov )
699 }
700 
701 /*
702 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
703 {
704  DEBUG_TRACE("")
705  if (updatesDisabled) return;
706  PanoramaOptions opt = pano->getOptions();
707  int vfov = m_VFOVSpin->GetValue() ;
708 
709  if (vfov != opt.getVFOV()) {
710  opt.setVFOV(vfov);
711  GlobalCmdHist::getInstance().addCommand(
712  new PanoCommand::SetPanoOptionsCmd( pano, opt )
713  );
714  DEBUG_INFO ( "new vfov: " << vfov << " => height: " << opt.getHeight() );
715  } else {
716  DEBUG_DEBUG("not setting same fov");
717  }
718 }
719 */
720 
721 void PanoPanel::WidthChanged ( wxCommandEvent & e )
722 {
723  if (updatesDisabled) return;
725  long nWidth;
726  if (m_WidthTxt->GetValue().ToLong(&nWidth)) {
727  if (nWidth <= 0) return;
728  opt.setWidth((unsigned int) nWidth, m_keepViewOnResize);
731  );
732  DEBUG_INFO(nWidth );
733  } else {
734  wxLogError(_("width needs to be an integer bigger than 0"));
735  }
736 }
737 
738 void PanoPanel::HeightChanged ( wxCommandEvent & e )
739 {
740  if (updatesDisabled) return;
742  long nHeight;
743  if (m_HeightTxt->GetValue().ToLong(&nHeight)) {
744  if(nHeight <= 0) return;
745  opt.setHeight((unsigned int) nHeight);
748  );
749  DEBUG_INFO(nHeight);
750  } else {
751  wxLogError(_("height needs to be an integer bigger than 0"));
752  }
753 }
754 
755 void PanoPanel::ROIChanged ( wxCommandEvent & e )
756 {
757  if (updatesDisabled) return;
759  long left, right, top, bottom;
760  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
761  wxLogError(_("Top needs to be an integer bigger than 0"));
762  return;
763  }
764  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
765  wxLogError(_("left needs to be an integer bigger than 0"));
766  return;
767  }
768  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
769  wxLogError(_("right needs to be an integer bigger than 0"));
770  return;
771  }
772  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
773  wxLogError(_("bottom needs to be an integer bigger than 0"));
774  return;
775  }
776  opt.setROI(vigra::Rect2D(left, top, right, bottom));
777 
778  // make sure that left is really to the left of right
779  if(opt.getROI().width()<1) {
780  wxLogError(_("Left boundary must be smaller than right."));
781  UpdateDisplay(pano->getOptions(), false);
782  return;
783  }
784  // make sure that top is really higher than bottom
785  if(opt.getROI().height()<1) {
786  wxLogError(_("Top boundary must be smaller than bottom."));
787  UpdateDisplay(pano->getOptions(), false);
788  return;
789  }
790 
793  );
794 }
795 
796 
797 void PanoPanel::EnableControls(bool enable)
798 {
799 // m_HFOVSpin->Enable(enable);
800 // m_VFOVSpin->Enable(enable);
801  m_WidthTxt->Enable(enable);
802  m_RemapperChoice->Enable(enable);
803  m_BlenderChoice->Enable(enable);
804 // m_CalcHFOVButton->Enable(enable);
805 // m_CalcOptWidthButton->Enable(enable);
806 // m_CalcOptROIButton->Enable(enable);
807 }
808 
809 void PanoPanel::RemapperChanged(wxCommandEvent & e)
810 {
811  int remapper = m_RemapperChoice->GetSelection();
812  DEBUG_DEBUG("changing remapper to " << remapper);
813 
815  if (remapper == 1) {
817  } else {
819  }
820 
823  );
824 }
825 
826 void PanoPanel::OnRemapperOptions(wxCommandEvent & e)
827 {
830  wxDialog dlg;
831  wxXmlResource::Get()->LoadDialog(&dlg, this, "nona_options_dialog");
832  wxChoice * interpol_choice = XRCCTRL(dlg, "nona_choice_interpolator", wxChoice);
833  wxCheckBox * cropped_cb = XRCCTRL(dlg, "nona_save_cropped", wxCheckBox);
834  interpol_choice->SetSelection(opt.interpolator);
835  cropped_cb->SetValue(opt.tiff_saveROI);
836  dlg.CentreOnParent();
837 
838  if (dlg.ShowModal() == wxID_OK) {
839  int interpol = interpol_choice->GetSelection();
840  if (interpol >= 0) {
841  opt.interpolator = (vigra_ext::Interpolator) interpol;
842  }
843  opt.tiff_saveROI = cropped_cb->GetValue();
846  );
847  }
848  } else {
849  wxLogError(_("PTmender options not yet implemented"));
850  }
851 }
852 
853 void PanoPanel::BlenderChanged(wxCommandEvent & e)
854 {
857 
860  );
861 }
862 
863 void PanoPanel::OnBlenderOptions(wxCommandEvent & e)
864 {
867  wxDialog dlg;
868  wxXmlResource::Get()->LoadDialog(&dlg, this, "enblend_options_dialog");
869  wxTextCtrl * enblend_opts_text = XRCCTRL(dlg, "blender_arguments_text", wxTextCtrl);
870  enblend_opts_text->ChangeValue(wxString(opt.enblendOptions.c_str(), wxConvLocal));
871  dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp("Enblend.html"); }, wxID_HELP);
872  dlg.CentreOnParent();
873 
874  if (dlg.ShowModal() == wxID_OK) {
875  opt.enblendOptions = enblend_opts_text->GetValue().mb_str(wxConvLocal);
878  );
879  }
880  }
881  else
882  {
884  {
885  wxDialog dlg;
886  wxXmlResource::Get()->LoadDialog(&dlg, this, "verdandi_options_dialog");
887  wxChoice * verdandiBlendModeChoice = XRCCTRL(dlg, "verdandi_blend_mode_choice", wxChoice);
888  if (opt.verdandiOptions.find("--seam=blend")!=std::string::npos)
889  {
890  verdandiBlendModeChoice->SetSelection(1);
891  }
892  else
893  {
894  verdandiBlendModeChoice->SetSelection(0);
895  };
896  dlg.CentreOnParent();
897 
898  if (dlg.ShowModal() == wxID_OK)
899  {
900  if (verdandiBlendModeChoice->GetSelection() == 1)
901  {
902  opt.verdandiOptions = "--seam=blend";
903  }
904  else
905  {
906  opt.verdandiOptions = "";
907  };
909  };
910  }
911  else
912  {
913  wxLogError(_("PTblender options not yet implemented"));
914  };
915  };
916 }
917 
918 void PanoPanel::OnEdgeFillChanged(wxCommandEvent & e)
919 {
922  {
923  if (opt.edgeFillMode != newMode)
924  {
925  opt.edgeFillMode = newMode;
928  );
929  };
930  };
931 }
932 
933 void PanoPanel::OnEdgeFillOptions(wxCommandEvent& e)
934 {
936  wxDialog dlg;
937  wxXmlResource::Get()->LoadDialog(&dlg, this, "filledge_options_dialog");
938  wxCheckBox* keepUnfillVersion = XRCCTRL(dlg, "edgefill_save_input", wxCheckBox);
939  keepUnfillVersion->SetValue(opt.keepEdgeFillInput);
940  dlg.CentreOnParent();
941 
942  if (dlg.ShowModal() == wxID_OK)
943  {
944  opt.keepEdgeFillInput = keepUnfillVersion->IsChecked();
946  };
947 }
948 
949 void PanoPanel::FusionChanged(wxCommandEvent & e)
950 {
951  int fusion = m_FusionChoice->GetSelection();
952  DEBUG_DEBUG("changing stacking program to " << fusion);
953 }
954 
955 void PanoPanel::OnFusionOptions(wxCommandEvent & e)
956 {
958  wxDialog dlg;
959  wxXmlResource::Get()->LoadDialog(&dlg, this, "enfuse_options_dialog");
960  wxTextCtrl * enfuse_opts_text = XRCCTRL(dlg, "enfuse_arguments_text", wxTextCtrl);
961  enfuse_opts_text->ChangeValue(wxString(opt.enfuseOptions.c_str(), wxConvLocal));
962  dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp("Enfuse.html"); }, wxID_HELP);
963  dlg.CentreOnParent();
964 
965  if (dlg.ShowModal() == wxID_OK) {
966  opt.enfuseOptions = enfuse_opts_text->GetValue().mb_str(wxConvLocal);
969  );
970  }
971 }
972 
973 
974 void PanoPanel::HDRMergeChanged(wxCommandEvent & e)
975 {
976  int blender = m_HDRMergeChoice->GetSelection();
977  DEBUG_DEBUG("changing HDR merger to " << blender);
978 }
979 
980 void PanoPanel::OnHDRMergeOptions(wxCommandEvent & e)
981 {
984  HDRMergeOptionsDialog dlg(this);
985  dlg.SetCommandLineArgument(wxString(opt.hdrmergeOptions.c_str(), wxConvLocal));
986  if (dlg.ShowModal() == wxOK)
987  {
988  opt.hdrmergeOptions=dlg.GetCommandLineArgument().mb_str(wxConvLocal);
991  );
992  }
993  } else {
994  wxLogError(_("Options for this HDRMerge program not yet implemented"));
995  }
996 }
997 
998 
999 
1000 void PanoPanel::DoCalcFOV(wxCommandEvent & e)
1001 {
1002  DEBUG_TRACE("");
1003  if (pano->getActiveImages().empty()) return;
1004 
1007  fitPano.run();
1008  opt.setHFOV(fitPano.getResultHorizontalFOV());
1010 
1011  DEBUG_INFO ( "hfov: " << opt.getHFOV() << " w: " << opt.getWidth() << " h: " << opt.getHeight() << " => vfov: " << opt.getVFOV() << " before update");
1012 
1015  );
1016 
1018  DEBUG_INFO ( "hfov: " << opt2.getHFOV() << " w: " << opt2.getWidth() << " h: " << opt2.getHeight() << " => vfov: " << opt2.getVFOV() << " after update");
1019 
1020 }
1021 
1022 void PanoPanel::DoCalcOptimalWidth(wxCommandEvent & e)
1023 {
1024  if (pano->getActiveImages().empty()) return;
1025 
1027  double sizeFactor = 1.0;
1028  if (wxGetKeyState(WXK_COMMAND))
1029  {
1030  wxConfigBase::Get()->Read("/Assistant/panoDownsizeFactor", &sizeFactor, HUGIN_ASS_PANO_DOWNSIZE_FACTOR);
1031  };
1032 
1034 
1035  if (width > 0) {
1036  opt.setWidth( width );
1039  );
1040  }
1041  DEBUG_INFO ( "new optimal width: " << opt.getWidth() );
1042 }
1043 
1044 
1045 void PanoPanel::DoCalcOptimalROI(wxCommandEvent & e)
1046 {
1047  DEBUG_INFO("Dirty ROI Calc\n");
1048  if (pano->getActiveImages().empty())
1049  {
1050  return;
1051  };
1052 
1053  vigra::Rect2D newROI;
1054  {
1055  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
1056  HuginBase::CalculateOptimalROI cropPano(*pano, &progress);
1057  cropPano.run();
1058  if (cropPano.hasRunSuccessfully())
1059  {
1060  newROI = cropPano.getResultOptimalROI();
1061  };
1062  };
1063 
1064  //set the ROI - fail if the right/bottom is zero, meaning all zero
1065  if(!newROI.isEmpty())
1066  {
1068  opt.setROI(newROI);
1071  );
1072  };
1073 };
1074 
1075 void PanoPanel::DoStitch(const wxString& userDefinedSetting, const bool readSetting)
1076 {
1077  if (pano->getNrOfImages() == 0) {
1078  return;
1079  }
1080 
1081  if (!CheckGoodSize()) {
1082  // oversized pano and the user no longer wants to stitch.
1083  return;
1084  }
1085  if (!CheckHasImages())
1086  {
1087  // output ROI contains no images
1088  return;
1089  };
1090 
1091  // save project
1092  // copy pto file to temporary file
1093  wxString tempDir= wxConfigBase::Get()->Read("tempDir",wxEmptyString);
1094  if(!tempDir.IsEmpty())
1095  if(tempDir.Last()!=wxFileName::GetPathSeparator())
1096  tempDir.Append(wxFileName::GetPathSeparator());
1097  wxString currentPTOfn = wxFileName::CreateTempFileName(tempDir+"huginpto_");
1098  if(currentPTOfn.empty()) {
1099  hugin_utils::HuginMessageBox(_("Could not create temporary project file"), _("Hugin"), wxCANCEL | wxICON_ERROR, wxGetActiveWindow());
1100  return;
1101  }
1102  DEBUG_DEBUG("tmp PTO file: " << (const char *)currentPTOfn.mb_str(wxConvLocal));
1103  // copy is not enough, need to adjust image path names...
1104  pano->WritePTOFile(std::string(currentPTOfn.mb_str(HUGIN_CONV_FILENAME)));
1105 
1106 // wxCommandEvent dummy;
1107 // MainFrame::Get()->OnSaveProject(dummy);
1108 
1109 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
1110  // HuginStitchProject inside main bundle
1111  wxString hugin_stitch_project = MacGetPathToBundledAppMainExecutableFile(CFSTR("HuginStitchProject.app"));
1112  if(hugin_stitch_project == wxEmptyString)
1113  {
1114  DEBUG_ERROR("hugin_stitch_project could not be found in the bundle.");
1115  return;
1116  }
1117  hugin_stitch_project = hugin_utils::wxQuoteFilename(hugin_stitch_project);
1118 #elif defined __WXMAC__
1119  // HuginStitchProject installed in INSTALL_OSX_BUNDLE_DIR
1120  wxFileName hugin_stitch_project_app(INSTALL_OSX_BUNDLE_DIR, wxEmptyString);
1121  hugin_stitch_project_app.AppendDir("HuginStitchProject.app");
1122  CFStringRef stitchProjectAppPath = MacCreateCFStringWithWxString(hugin_stitch_project_app.GetFullPath());
1123  wxString hugin_stitch_project = MacGetPathToMainExecutableFileOfBundle(stitchProjectAppPath);
1124  CFRelease(stitchProjectAppPath);
1125 #else
1126  wxString hugin_stitch_project = "hugin_stitch_project";
1127 #endif
1128 
1129  // Derive a default output prefix from the project filename if set, otherwise default project filename
1130  wxFileName outputPrefix(getDefaultOutputName(MainFrame::Get()->getProjectName(), *pano));
1131  outputPrefix.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
1132 
1133  // Show a file save dialog so user can confirm/change the prefix.
1134  // (We don't have to worry about overwriting existing files, since hugin_switch_project checks this.)
1135  // TODO: The following code is similar to stitchApp::OnInit in hugin_switch_project.cpp. Should be refactored.
1136  // TODO: We should save the output prefix somewhere, so we can recall it as the default if the user stitches this project again.
1137  wxFileDialog dlg(this,_("Specify output prefix"),
1138  outputPrefix.GetPath(), outputPrefix.GetName(), wxEmptyString,
1139  wxFD_SAVE, wxDefaultPosition);
1140  if (dlg.ShowModal() != wxID_OK)
1141  {
1142  return;
1143  };
1144  while(containsInvalidCharacters(dlg.GetPath()))
1145  {
1146  wxArrayString list;
1147  list.Add(dlg.GetPath());
1148  ShowFilenameWarning(this, list);
1149  if(dlg.ShowModal()!=wxID_OK)
1150  return;
1151  };
1152  wxFileName prefix(dlg.GetPath());
1153  while (!prefix.IsDirWritable())
1154  {
1155  hugin_utils::HuginMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath()),
1156  _("Hugin"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
1157  if (dlg.ShowModal() != wxID_OK)
1158  {
1159  return;
1160  };
1161  prefix = dlg.GetPath();
1162  };
1163  // check free space
1164  if (!CheckFreeSpace(prefix.GetPath()))
1165  {
1166  return;
1167  };
1168 
1169  wxString switches(" --delete -o ");
1170  if (readSetting && wxConfigBase::Get()->Read("/Processor/overwrite", HUGIN_PROCESSOR_OVERWRITE) == 1)
1171  {
1172  switches = " --overwrite" + switches;
1173  };
1174  if (!userDefinedSetting.IsEmpty())
1175  {
1176  switches = " --user-defined-output=" + hugin_utils::wxQuoteFilename(userDefinedSetting) + " " + switches;
1177  };
1178  wxString command = hugin_stitch_project + switches + hugin_utils::wxQuoteFilename(dlg.GetPath()) + " " + hugin_utils::wxQuoteFilename(currentPTOfn);
1179 
1180  wxConfigBase::Get()->Flush();
1181 #ifdef __WXGTK__
1182  // work around a wxExecute bug/problem
1183  // (endless polling of fd 0 and 1 in hugin_stitch_project)
1184  wxProcess *my_process = new wxProcess(this);
1185  my_process->Redirect();
1186 
1187  // Delete itself once processes terminated.
1188  my_process->Detach();
1189  wxExecute(command,wxEXEC_ASYNC, my_process);
1190 #else
1191  wxExecute(command);
1192 #endif
1194 }
1195 
1196 void PanoPanel::DoSendToBatch(const wxString& userDefinedSetting)
1197 {
1198  if (pano->getNrOfImages() == 0)
1199  {
1200  return;
1201  }
1202 
1203  if (!CheckGoodSize())
1204  {
1205  // oversized pano and the user no longer wants to stitch.
1206  return;
1207  }
1208  if( !CheckHasImages())
1209  {
1210  // output ROI contains no images
1211  return;
1212  };
1213 
1214  wxString switches(" ");
1215  if (wxConfigBase::Get()->Read("/Processor/start", HUGIN_PROCESSOR_START) != 0)
1216  {
1217  switches += "-b ";
1218  };
1219  if (wxConfigBase::Get()->Read("/Processor/overwrite", HUGIN_PROCESSOR_OVERWRITE) != 0)
1220  {
1221  switches += "-o ";
1222  };
1223  if (wxConfigBase::Get()->Read("/Processor/verbose", HUGIN_PROCESSOR_VERBOSE) != 0)
1224  {
1225  switches += "-v ";
1226  };
1227  if (!userDefinedSetting.IsEmpty())
1228  {
1229  switches += "--user-defined=" + hugin_utils::wxQuoteFilename(userDefinedSetting) + " ";
1230  };
1231  if(pano->isDirty())
1232  {
1233  bool showDlg=wxConfigBase::Get()->Read("ShowSaveMessage", 1l)==1;
1234  if(showDlg)
1235  {
1236  // show information that project file needs to be saved first
1237  // and user has to give the output prefix afterwards
1238  wxDialog dlg;
1239  wxXmlResource::Get()->LoadDialog(&dlg, this, "stitch_message_dlg");
1240  if (!(MainFrame::Get()->getProjectName().IsEmpty()))
1241  {
1242  // project file was already saved with a name, adapt message text for this use case
1243  XRCCTRL(dlg, "stitch_message_text", wxStaticText)->SetLabel(
1244  wxString::Format(_("The project %s will be automatically saved before it can be sent to the batch processor PTBatcherGUI.\nYou will then be asked for the prefix for the panorama output.\n\nYou may need to start the stitching in the batch processor\n PTBatcherGUI if it doesn't start automatically."),
1245  MainFrame::Get()->getProjectName().c_str()
1246  )
1247  );
1248  };
1249  if(dlg.ShowModal())
1250  {
1251  if(XRCCTRL(dlg, "stitch_dont_show_checkbox", wxCheckBox)->IsChecked())
1252  {
1253  wxConfigBase::Get()->Write("ShowSaveMessage", 0l);
1254  };
1255  };
1256  };
1257  wxCommandEvent dummy;
1258  MainFrame::Get()->OnSaveProject(dummy);
1259  //test if save was sucessful
1260  if(pano->isDirty())
1261  {
1262  return;
1263  };
1264  };
1265  wxString projectFile = MainFrame::Get()->getProjectName();
1266  if(wxFileName::FileExists(projectFile))
1267  {
1268  wxFileName outputPrefix(getDefaultOutputName(projectFile, *pano));
1269  outputPrefix.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
1270 
1271  // Show a file save dialog so user can confirm/change the prefix.
1272  // (We don't have to worry about overwriting existing files, since PTBatcherGUI checks this, or the overwrite flag was set.)
1273  wxFileDialog dlg(this,_("Specify output prefix"),
1274  outputPrefix.GetPath(), outputPrefix.GetName(), wxEmptyString,
1275  wxFD_SAVE, wxDefaultPosition);
1276  if (dlg.ShowModal() != wxID_OK)
1277  {
1278  return;
1279  };
1280  while(containsInvalidCharacters(dlg.GetPath()))
1281  {
1282  wxArrayString list;
1283  list.Add(dlg.GetPath());
1284  ShowFilenameWarning(this, list);
1285  if(dlg.ShowModal()!=wxID_OK)
1286  return;
1287  };
1288  wxFileName prefix(dlg.GetPath());
1289  while (!prefix.IsDirWritable())
1290  {
1291  hugin_utils::HuginMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath()),
1292  _("Hugin"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
1293  if (dlg.ShowModal() != wxID_OK)
1294  {
1295  return;
1296  };
1297  prefix = dlg.GetPath();
1298  };
1299  // check free space
1300  if (!CheckFreeSpace(prefix.GetPath()))
1301  {
1302  return;
1303  };
1304 
1305 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
1306  wxString cmd = MacGetPathToMainExecutableFileOfRegisteredBundle(CFSTR("net.sourceforge.hugin.PTBatcherGUI"));
1307  if(cmd != wxEmptyString)
1308  {
1309  //Found PTBatcherGui inside the (registered) PTBatcherGui bundle. Call it directly.
1310  //We need to call the binary from it's own bundle and not from the hugin bundle otherwise we get no menu as OSX assumes that the hugin bundle
1311  //will provide the menu
1312  cmd = hugin_utils::wxQuoteString(cmd);
1313  cmd += " " + switches + hugin_utils::wxQuoteFilename(projectFile) + " " + hugin_utils::wxQuoteFilename(dlg.GetPath());
1314  wxExecute(cmd);
1315  }
1316  else
1317  { //Can't find PTBatcherGui.app bundle. Use the most straightforward call possible to the bundle but this should actually not work either.
1318  hugin_utils::HuginMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), "open"), _("Hugin"), wxOK | wxICON_ERROR, wxGetActiveWindow());
1319  cmd = "open -b net.sourceforge.hugin.PTBatcherGUI "+hugin_utils::wxQuoteFilename(projectFile);
1320  wxExecute(cmd);
1321  }
1322 
1323 #else
1324  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
1325  wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "PTBatcherGUI " + switches + hugin_utils::wxQuoteFilename(projectFile) + " " + hugin_utils::wxQuoteFilename(dlg.GetPath()));
1326 #endif
1328  }
1329 };
1330 
1331 void PanoPanel::DoUserDefinedStitch(const wxString& settings)
1332 {
1333  if (pano->getNrOfImages() == 0)
1334  {
1335  return;
1336  }
1337 
1338  if (!CheckGoodSize())
1339  {
1340  // oversized pano and the user no longer wants to stitch.
1341  return;
1342  }
1343  if (!CheckHasImages())
1344  {
1345  // output ROI contains no images
1346  return;
1347  };
1348  wxFileName userOutputSequence;
1349  if (settings.IsEmpty())
1350  {
1351  // no filename given, ask user
1352  wxConfigBase* config = wxConfigBase::Get();
1353  wxString path = config->Read("/userDefinedOutputPath", MainFrame::Get()->GetDataPath());
1354  wxFileDialog userOutputDlg(this, _("Select user defined output"),
1355  path, wxEmptyString, _("User defined output|*.executor"),
1356  wxFD_OPEN | wxFD_FILE_MUST_EXIST, wxDefaultPosition);
1357  if (userOutputDlg.ShowModal() != wxID_OK)
1358  {
1359  return;
1360  };
1361  // remember path for later
1362  config->Write("/userDefinedOutputPath", userOutputDlg.GetDirectory());
1363  userOutputSequence = userOutputDlg.GetPath();
1364  }
1365  else
1366  {
1367  //filename given, check existance
1368  userOutputSequence = settings;
1369  if (!userOutputSequence.Exists())
1370  {
1371  hugin_utils::HuginMessageBox(wxString::Format("User defined output %s not found.\nStopping processing.", userOutputSequence.GetFullPath()), _("Hugin"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
1372  return;
1373  };
1374  };
1375  DoStitchOrSendBatch(userOutputSequence.GetFullPath());
1376 }
1377 
1378 void PanoPanel::DoStitchOrSendBatch(const wxString& userDefinedSetting)
1379 {
1380  long t;
1381  bool readSettings = true;
1382  if(wxGetKeyState(WXK_COMMAND))
1383  {
1384  t=1;
1385  readSettings = false;
1386  }
1387  else
1388  {
1389  wxConfigBase::Get()->Read("/Processor/gui", &t, HUGIN_PROCESSOR_GUI);
1390  };
1391  switch (t)
1392  {
1393  // PTBatcher
1394  case 0:
1395  DoSendToBatch(userDefinedSetting);
1396  break;
1397  // hugin_stitch_project
1398  case 1:
1399  DoStitch(userDefinedSetting, readSettings);
1400  break;
1401  // there is an error in the preferences
1402  default :
1403  // TODO: notify user and fix preferences misconfiguration
1404  break;
1405  }
1406 }
1407 
1408 void PanoPanel::OnDoStitch(wxCommandEvent& e)
1409 {
1411 }
1412 
1413 void PanoPanel::FileFormatChanged(wxCommandEvent & e)
1414 {
1415 
1416  int fmt = m_FileFormatChoice->GetSelection();
1417  DEBUG_DEBUG("changing file format to " << fmt);
1418 
1420  switch (fmt) {
1421  case 1:
1422  opt.outputImageType ="jpg";
1423  break;
1424  case 2:
1425  opt.outputImageType ="png";
1426  break;
1427  case 3:
1428  opt.outputImageType ="exr";
1429  break;
1430  default:
1431  case 0:
1432  opt.outputImageType ="tif";
1433  break;
1434  }
1435 
1438  );
1439 }
1440 
1441 void PanoPanel::HDRFileFormatChanged(wxCommandEvent & e)
1442 {
1443 
1444  int fmt = m_HDRFileFormatChoice->GetSelection();
1445  DEBUG_DEBUG("changing file format to " << fmt);
1446 
1448  switch (fmt) {
1449  case 1:
1450  opt.outputImageTypeHDR ="tif";
1451  break;
1452  default:
1453  case 0:
1454  opt.outputImageTypeHDR ="exr";
1455  break;
1456  }
1457 
1460  );
1461 }
1462 
1463 void PanoPanel::OnJPEGQualityText(wxCommandEvent & e)
1464 {
1466  long l = 100;
1467  m_FileFormatJPEGQualityText->GetValue().ToLong(&l);
1468  if (l < 0) l=1;
1469  if (l > 100) l=100;
1470  DEBUG_DEBUG("Setting jpeg quality to " << l);
1471  opt.quality = l;
1474  );
1475 }
1476 
1477 void PanoPanel::OnNormalTIFFCompression(wxCommandEvent & e)
1478 {
1480  switch(e.GetSelection()) {
1481  case 0:
1482  default:
1483  opt.outputImageTypeCompression = "NONE";
1484  opt.tiffCompression = "NONE";
1485  break;
1486  case 1:
1487  opt.outputImageTypeCompression = "PACKBITS";
1488  opt.tiffCompression = "PACKBITS";
1489  break;
1490  case 2:
1491  opt.outputImageTypeCompression = "LZW";
1492  opt.tiffCompression = "LZW";
1493  break;
1494  case 3:
1495  opt.outputImageTypeCompression = "DEFLATE";
1496  opt.tiffCompression = "DEFLATE";
1497  break;
1498  }
1501  );
1502 }
1503 
1504 void PanoPanel::OnHDRTIFFCompression(wxCommandEvent & e)
1505 {
1507  switch(e.GetSelection()) {
1508  case 0:
1509  default:
1510  opt.outputImageTypeHDRCompression = "NONE";
1511  break;
1512  case 1:
1513  opt.outputImageTypeHDRCompression = "PACKBITS";
1514  break;
1515  case 2:
1516  opt.outputImageTypeHDRCompression = "LZW";
1517  break;
1518  case 3:
1519  opt.outputImageTypeHDRCompression = "DEFLATE";
1520  break;
1521  }
1524  );
1525 }
1526 
1527 void PanoPanel::OnOutputFilesChanged(wxCommandEvent & e)
1528 {
1529  int id = e.GetId();
1531 
1532  if (id == XRCID("pano_cb_ldr_output_blended") ) {
1533  opts.outputLDRBlended = e.IsChecked();
1534  } else if (id == XRCID("pano_cb_ldr_output_layers") ) {
1535  opts.outputLDRLayers = e.IsChecked();
1536  } else if (id == XRCID("pano_cb_ldr_output_exposure_layers") ) {
1537  opts.outputLDRExposureLayers = e.IsChecked();
1538  } else if (id == XRCID("pano_cb_ldr_output_exposure_blended") ) {
1539  opts.outputLDRExposureBlended = e.IsChecked();
1540  } else if (id == XRCID("pano_cb_ldr_output_exposure_layers_fused") ) {
1541  opts.outputLDRExposureLayersFused = e.IsChecked();
1542  } else if (id == XRCID("pano_cb_ldr_output_exposure_remapped") ) {
1543  opts.outputLDRExposureRemapped = e.IsChecked();
1544  } else if (id == XRCID("pano_cb_ldr_output_stacks") ) {
1545  opts.outputLDRStacks = e.IsChecked();
1546  } else if (id == XRCID("pano_cb_hdr_output_blended") ) {
1547  opts.outputHDRBlended = e.IsChecked();
1548  } else if (id == XRCID("pano_cb_hdr_output_stacks") ) {
1549  opts.outputHDRStacks = e.IsChecked();
1550  } else if (id == XRCID("pano_cb_hdr_output_layers") ) {
1551  opts.outputHDRLayers = e.IsChecked();
1552  }
1553 
1555  new PanoCommand::SetPanoOptionsCmd( *pano, opts )
1556  );
1557 }
1558 
1560 {
1562  const vigra::Rect2D cropped_region (opts.getROI());
1563  // width and height of jpeg images has to be smaller than 65500 pixel
1564  if (opts.outputImageType == "jpg" &&
1565  (opts.outputLDRBlended || opts.outputLDRExposureBlended || opts.outputLDRExposureLayersFused) &&
1566  (cropped_region.width()>65500 || cropped_region.height()>65500)
1567  )
1568  {
1570  wxString::Format(_("The width and height of jpeg images has to be smaller than 65500 pixel. But you have requested a jpeg image with %dx%d pixel.\nThis is not supported by the jpeg file format.\nDecrease the canvas size on the stitch panel or select TIF or PNG as output format."), cropped_region.width(), cropped_region.height()),
1571  _("Hugin"), wxICON_EXCLAMATION | wxOK, wxGetActiveWindow());
1572  return false;
1573  };
1574  wxString message;
1575  const unsigned long long area = (static_cast<unsigned long long>(cropped_region.width()) * cropped_region.height());
1576  // Argh, more than half a gigapixel!
1577  if (area > 500000000)
1578  {
1579  message = wxString::Format(_("The panorama you are trying to stitch is %.1f gigapixels.\nIf this is too big, reduce the panorama Canvas Size and the cropped region and stitch from the Stitcher tab. Stitching a panorama this size could take a long time and a large amount of memory."),
1580  area / 1000000000.0);
1581  }
1582  else
1583  {
1584  if (cropped_region.width() > 32700 || cropped_region.height() > 32700)
1585  {
1586  message = _("The width or the height of the final panorama exceeds 32700 pixel.\nSome programs have problems to open or display such big images.\n\nIf this is too big, reduce the panorama Canvas Size or the cropped region.");
1587  };
1588  };
1589  if (!message.empty())
1590  {
1591  // Tell the user the stitch will be really big, and give them a
1592  // chance to reduce the size.
1593  hugin_utils::MessageDialog dialog = hugin_utils::GetMessageDialog(_("Are you sure you want to stitch such a large panorama?"),
1594  _("Hugin"), wxICON_EXCLAMATION | wxYES_NO, wxGetActiveWindow());
1595  dialog->SetExtendedMessage(message);
1596  dialog->SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
1597  switch (dialog->ShowModal())
1598  {
1599  case wxID_OK:
1600  case wxID_YES:
1601  // Continue stitch.
1602  return true;
1603  break;
1604  default:
1605  // bring the user towards the approptiate controls.
1606  MainFrame* mainframe = MainFrame::Get();
1607  if (!mainframe->IsShown())
1608  {
1609  mainframe->Show();
1610  }
1611  mainframe->ShowStitcherTab();
1612  return false;
1613  }
1614  }
1615  // I see nothing wrong with this...
1616  return true;
1617 }
1618 
1620 {
1622  if(images.empty())
1623  {
1624  hugin_utils::HuginMessageBox(_("There are no active images in the output region.\nPlease check your settings, so that at least one image is in the output region."),
1625  _("Hugin"), wxOK | wxICON_INFORMATION, wxGetActiveWindow());
1626  };
1627  return !images.empty();
1628 };
1629 
1630 bool PanoPanel::CheckFreeSpace(const wxString& folder)
1631 {
1632  wxLongLong freeSpace;
1633  if (wxGetDiskSpace(folder, NULL, &freeSpace))
1634  {
1635  // 4 channels, 16 bit per channel, assuming the we need the 10 fold space for all temporary space
1636  if (pano->getOptions().getROI().area() * 80 > freeSpace)
1637  {
1638  hugin_utils::MessageDialog dialog = hugin_utils::GetMessageDialog(wxString::Format(_("The folder \"%s\" has only %.1f MiB free. This is not enough for stitching the current panorama. Decrease the output size or select another output folder.\nAre you sure that you still want to stitch it?"), folder.c_str(), freeSpace.ToDouble() / 1048576.0),
1639  _("Hugin"), wxICON_EXCLAMATION | wxYES_NO, wxGetActiveWindow());
1640  dialog->SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
1641  if (dialog->ShowModal() == wxID_NO)
1642  {
1643  // bring the user towards the approptiate controls.
1644  MainFrame* mainframe = MainFrame::Get();
1645  if (!mainframe->IsShown())
1646  {
1647  mainframe->Show();
1648  }
1649  mainframe->ShowStitcherTab();
1650  return false;
1651  };
1652  };
1653  };
1654  return true;
1655 };
1656 
1658 {
1659  m_guiLevel=newGuiLevel;
1660  UpdateDisplay(m_oldOpt, false);
1661 };
1662 
1664 
1666  : wxXmlResourceHandler()
1667 {
1668  AddWindowStyles();
1669 }
1670 
1672 {
1673  XRC_MAKE_INSTANCE(cp, PanoPanel)
1674 
1675  cp->Create(m_parentAsWindow,
1676  GetID(),
1677  GetPosition(), GetSize(),
1678  GetStyle("style"),
1679  GetName());
1680 
1681  SetupWindow( cp);
1682 
1683  return cp;
1684 }
1685 
1686 bool PanoPanelXmlHandler::CanHandle(wxXmlNode *node)
1687 {
1688  return IsOfClass(node, "PanoPanel");
1689 }
1690 
1691 IMPLEMENT_DYNAMIC_CLASS(PanoPanelXmlHandler, wxXmlResourceHandler)
1692 
void DisplayHelp(wxString section=wxEmptyString)
call help browser with given file
Definition: MainFrame.cpp:1459
#define DEBUG_INFO(msg)
Definition: utils.h:69
int floori(double x)
Definition: hugin_math.h:65
Dialog for reset panorama settings.
bool CheckHasImages()
check if the output contains images at all
Definition: PanoPanel.cpp:1619
void OnBlenderOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:863
void SetCommandLineArgument(wxString cmd)
sets the currents state of the hdrmerge options
int gcd(int a, int b)
function to calculate greated common divisor using Euclidean algorithm both arguments should be &gt;=0 ...
Definition: hugin_math.cpp:35
PanoramaOptions::ProjectionFormat getProjection() const
void BlenderChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:853
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
Definition: LayerStacks.cpp:35
implementation of huginApp Class
bool FileExists(const std::string &filename)
checks if file exists
Definition: utils.cpp:362
void HeightChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:738
declaration of functions to handle stacks and layers
void OnNormalTIFFCompression(wxCommandEvent &e)
Definition: PanoPanel.cpp:1477
wxString GetDataPath()
return path to data directory, it depends on operating system
bool CheckFreeSpace(const wxString &folder)
check if there is enough free disk space
Definition: PanoPanel.cpp:1630
void ShowStitcherTab()
opens the stitcher tab
Definition: MainFrame.cpp:2015
void setHeight(unsigned int h)
set panorama height
void EnableControls(bool enable)
enable/disable control influenced by quick mode
Definition: PanoPanel.cpp:797
int roundi(T x)
Definition: hugin_math.h:73
wxTextCtrl * m_ROITopTxt
Definition: PanoPanel.h:198
void DoCalcFOV(wxCommandEvent &e)
Definition: PanoPanel.cpp:1000
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void ProjectionChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:620
void ROIChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:755
virtual ~PanoPanel(void)
Definition: PanoPanel.cpp:258
bool outputLDRLayers
save remapped layers (LDR)
virtual wxObject * DoCreateResource()
Definition: PanoPanel.cpp:1671
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
std::unique_ptr< wxMessageDialogBase > MessageDialog
Definition: wxutils.h:87
misc math function &amp; classes used by other parts of the program
void OnFusionOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:955
#define DEBUG_TRACE(msg)
Definition: utils.h:67
Definition of CPImagesComboBox and CPImagesComboBoxXmlHandler class.
str wxQuoteString(const str &arg)
Try to escape special chars on windows and linux.
Definition: wxPlatform.h:66
void OnEdgeFillChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:918
std::string outputImageTypeHDRCompression
bool outputHDRLayers
save remapped layers (HDR)
unsigned int getHeight() const
get panorama height
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
wxTextCtrl * m_VFOVText
Definition: PanoPanel.h:192
some helper classes for graphes
void UpdateDisplay(const HuginBase::PanoramaOptions &opt, const bool hasStacks)
Definition: PanoPanel.cpp:347
wxButton * m_CalcOptWidthButton
Definition: PanoPanel.h:207
double getMaxHFOV() const
get maximum possible hfov with current projection
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
bool SaveLensDataFromPano(const HuginBase::Panorama &pano)
routine for automatically saving information from pano into database
Definition: LensDB.cpp:2553
HuginBase::Panorama * pano
Definition: PanoPanel.h:175
include file for the hugin project
wxString GetCommandLineArgument()
returns the hdrmerge options as command line arguments
virtual void run()
runs the algorithm.
std::string outputImageTypeCompression
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
Definition: PanoPanel.cpp:72
void DoUserDefinedStitch(const wxString &settings=wxString())
stitching with user defined file
Definition: PanoPanel.cpp:1331
wxScrolledWindow * m_pano_ctrls
Definition: PanoPanel.h:219
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition: utils.cpp:228
MessageDialog GetMessageDialog(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:212
void SetGuiLevel(GuiLevel newGuiLevel)
Definition: PanoPanel.cpp:1657
void ShowFilenameWarning(wxWindow *parent, const wxArrayString filelist)
shows a dialog about filename with invalid characters, all names in filelist will be show in list ...
Definition: platform.cpp:523
void OnRemapperOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:826
bool outputLDRExposureBlended
&lt; save exposure fused stacks (no exposure adjustment)
void VFOVChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:669
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
set the panorama options
Definition: PanoCommand.h:418
wxStaticText * m_FileFormatOptionsLabel
Definition: PanoPanel.h:211
class to access Hugins camera and lens database
void Init(HuginBase::Panorama *pano)
Definition: PanoPanel.cpp:250
The main window frame.
Definition: MainFrame.h:83
wxTextCtrl * m_ROIBottomTxt
Definition: PanoPanel.h:199
const vigra::Rect2D & getROI() const
Model for a panorama.
Definition: Panorama.h:152
Definition of dialog for hdrmerge options.
wxTextCtrl * m_WidthTxt
Definition: PanoPanel.h:194
bool outputLDRBlended
save blended panorama (LDR)
void RemapperChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:809
wxTextCtrl * m_ROILeftTxt
Definition: PanoPanel.h:196
wxChoice * m_BlenderChoice
Definition: PanoPanel.h:203
size_t GetSelectedValue(wxControlWithItems *list)
Returns the client value of the selected item from list.
Definition: LensTools.cpp:103
wxChoice * m_edgeFillChoice
Definition: PanoPanel.h:204
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2129
wxTextCtrl * m_FileFormatJPEGQualityText
Definition: PanoPanel.h:212
wxChoice * m_FusionChoice
Definition: PanoPanel.h:201
vigra_ext::Interpolator interpolator
float pow(float a, double b)
Definition: utils.h:181
virtual void panoramaChanged(HuginBase::Panorama &pano)
this is called whenever the panorama has changed.
Definition: PanoPanel.cpp:278
wxChoice * m_RemapperChoice
Definition: PanoPanel.h:200
wxTextCtrl * m_HeightTxt
Definition: PanoPanel.h:195
static double calcOptimalScale(PanoramaData &panorama)
wxTextCtrl * m_HFOVText
Definition: PanoPanel.h:191
virtual vigra::Rect2D getResultOptimalROI()
return the ROI structure?, for now area
double getMaxVFOV() const
get maximum possible vfov with current projection
virtual double getResultHeight()
Definition: FitPanorama.h:75
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
bool outputHDRBlended
save blended panorama (HDR)
void OnHDRTIFFCompression(wxCommandEvent &e)
Definition: PanoPanel.cpp:1504
static GlobalCmdHist & getInstance()
void OnEdgeFillOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:933
void FileFormatChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:1413
#define HUGIN_PROCESSOR_START
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
void FusionChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:949
wxChoice * m_HDRMergeChoice
Definition: PanoPanel.h:202
#define DEBUG_ERROR(msg)
Definition: utils.h:76
wxChoice * m_FileFormatHDRTIFFCompChoice
Definition: PanoPanel.h:217
void setROI(const vigra::Rect2D &val)
bool m_keepViewOnResize
Definition: PanoPanel.h:186
void WidthChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:721
void OnSaveProject(wxCommandEvent &e)
Definition: MainFrame.cpp:966
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
wxChoice * m_ProjectionChoice
Definition: PanoPanel.h:190
#define HUGIN_PROCESSOR_OVERWRITE
void OnJPEGQualityText(wxCommandEvent &e)
Definition: PanoPanel.cpp:1463
wxButton * m_CalcHFOVButton
Definition: PanoPanel.h:206
bool outputLDRExposureLayers
save blended exposure layers, do not perform fusion (no exposure adjustment)
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
wxButton * m_CalcOptROIButton
Definition: PanoPanel.h:208
Contains various routines used for stitching panoramas.
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
unsigned int getWidth() const
void HFOVChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:637
include file for the hugin project
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
bool updatesDisabled
Definition: PanoPanel.h:182
wxChoice * m_FileFormatTIFFCompChoice
Definition: PanoPanel.h:213
void DoStitch(const wxString &userDefinedSetting=wxEmptyString, const bool readSetting=true)
stitching using hugin_stitch_project
Definition: PanoPanel.cpp:1075
void SelectListValue(wxControlWithItems *list, size_t newValue)
Selects the given value (stored in the client data) in the given list item.
Definition: LensTools.cpp:90
bool outputLDRExposureRemapped
save remapped layers (no exposure adjustment)
wxButton * m_StitchButton
Definition: PanoPanel.h:205
wxStaticText * m_HDRFileFormatLabelTIFFCompression
Definition: PanoPanel.h:216
bool isDirty() const
true if there are unsaved changes
Definition: Panorama.h:636
void DoCalcOptimalROI(wxCommandEvent &e)
set the largest rectangle for crop ROI
Definition: PanoPanel.cpp:1045
bool outputLDRExposureLayersFused
save blended exposure layers which are then fused (no exposure adjustment)
static T max(T x, T y)
Definition: svm.cpp:65
xrc handler
Definition: PanoPanel.h:225
void DoCalcOptimalWidth(wxCommandEvent &e)
set the highest sensible width
Definition: PanoPanel.cpp:1022
void HDRFileFormatChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:1441
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
bool containsInvalidCharacters(const wxString stringToTest)
returns true, if the given strings contains invalid characters
Definition: platform.cpp:510
void DoSendToBatch(const wxString &userDefinedSetting=wxEmptyString)
stitching with PTBatcherGUI
Definition: PanoPanel.cpp:1196
#define HUGIN_ASS_PANO_DOWNSIZE_FACTOR
functions for interaction with the hugin configuration file
platform/compiler specific stuff.
wxChoice * m_FileFormatChoice
Definition: PanoPanel.h:210
bool WritePTOFile(const std::string &filename, const std::string &prefix="")
write data to given pto file
Definition: Panorama.cpp:2059
void DoStitchOrSendBatch(const wxString &userDefinedSetting=wxEmptyString)
general stitching command, selects PTBatcherGUI or hugin_stitch_project depending on the settings in ...
Definition: PanoPanel.cpp:1378
GuiLevel m_guiLevel
Definition: PanoPanel.h:177
#define HUGIN_PROCESSOR_GUI
bool CheckGoodSize()
Check the canvas size isn&#39;t overly huge, or the user knows what they are doing.
Definition: PanoPanel.cpp:1559
Define the pano edit panel.
Definition: PanoPanel.h:43
void OnHDRMergeOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:980
virtual bool CanHandle(wxXmlNode *node)
Definition: PanoPanel.cpp:1686
GuiLevel
Definition: GuiLevel.h:31
#define HUGIN_PROCESSOR_VERBOSE
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
ProjectionFormat
Projection of final panorama.
bool m_hasStacks
Definition: PanoPanel.h:187
void HDRMergeChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:974
Interpolator
enum with all interpolation methods
Definition: Interpolators.h:78
str wxQuoteFilename(const str &arg)
Quote a filename, so that it is surrounded by &quot;&quot;.
Definition: wxPlatform.h:82
wxString getDefaultOutputName(const wxString projectname, const HuginBase::Panorama &pano, const wxString filenameTemplate)
gets the default output prefix, based on filename and images in project the setting is read from the ...
wxString getProjectName()
Definition: MainFrame.cpp:2140
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
Panorama image options.
bool outputHDRStacks
save image stacks (HDR)
wxChoice * m_HDRFileFormatChoice
Definition: PanoPanel.h:215
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
BlendingMechanism blendMode
void OnOutputFilesChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:1527
void FillBlenderList(wxControlWithItems *list)
Fills a wxControlWithItem with all possible blender options, the client data contains the associated ...
Definition: LensTools.cpp:82
HuginBase::PanoramaOptions m_oldOpt
Definition: PanoPanel.h:183
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
void OnDoStitch(wxCommandEvent &e)
Definition: PanoPanel.cpp:1408
bool StackCheck(HuginBase::Panorama &pano)
Definition: PanoPanel.cpp:297
wxTextCtrl * m_ROIRightTxt
Definition: PanoPanel.h:197