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