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 
521  XRCCTRL(*this, "pano_button_fill_opts", wxButton)->Enable(m_guiLevel > GUI_SIMPLE);
522  XRCCTRL(*this, "pano_button_fill_opts", wxButton)->Show(m_guiLevel > GUI_SIMPLE);
523  XRCCTRL(*this, "pano_text_edgefill", wxStaticText)->Enable(m_guiLevel > GUI_SIMPLE);
524  XRCCTRL(*this, "pano_text_edgefill", wxStaticText)->Show(m_guiLevel > GUI_SIMPLE);
525 
526  // output file mode
527  bool ldr_pano_enabled = opt.outputLDRBlended ||
530 
531  XRCCTRL(*this, "pano_output_ldr_format_label", wxStaticText)->Enable(ldr_pano_enabled);
532  m_FileFormatOptionsLabel->Enable(ldr_pano_enabled);
533  m_FileFormatChoice->Enable(ldr_pano_enabled);
534  m_FileFormatJPEGQualityText->Enable(ldr_pano_enabled);
535  m_FileFormatTIFFCompChoice->Enable(ldr_pano_enabled);
536 
537  long i=0;
538  if (opt.outputImageType == "tif") {
539  i = 0;
540  m_FileFormatOptionsLabel->Show();
541  m_FileFormatOptionsLabel->SetLabel(_("Compression:"));
544  if (opt.outputImageTypeCompression == "PACKBITS") {
545  m_FileFormatTIFFCompChoice->SetSelection(1);
546  } else if (opt.outputImageTypeCompression == "LZW") {
547  m_FileFormatTIFFCompChoice->SetSelection(2);
548  } else if (opt.outputImageTypeCompression == "DEFLATE") {
549  m_FileFormatTIFFCompChoice->SetSelection(3);
550  } else {
551  m_FileFormatTIFFCompChoice->SetSelection(0);
552  }
553  } else if (opt.outputImageType == "jpg") {
554  i = 1;
555  m_FileFormatOptionsLabel->Show();
556  m_FileFormatOptionsLabel->SetLabel(_("Quality:"));
559  m_FileFormatJPEGQualityText->ChangeValue(wxString::Format(wxT("%d"), opt.quality));
560  } else if (opt.outputImageType == "png") {
561  m_FileFormatOptionsLabel->Hide();
564  i = 2;
565  } else if (opt.outputImageType == "exr") {
567  m_FileFormatOptionsLabel->Hide();
570  i = 3;
571  } else
572  wxLogError(wxT("INTERNAL error: unknown output image type"));
573 
574  m_FileFormatChoice->SetSelection(i);
575 
576  bool hdr_pano_enabled = opt.outputHDRBlended;
577 
578  XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Enable(hdr_pano_enabled);
579  XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
580  m_HDRFileFormatChoice->Enable(hdr_pano_enabled);
581  m_HDRFileFormatChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
582  m_HDRFileFormatLabelTIFFCompression->Enable(hdr_pano_enabled);
583  m_HDRFileFormatLabelTIFFCompression->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
584  m_FileFormatHDRTIFFCompChoice->Enable(hdr_pano_enabled);
585  m_FileFormatHDRTIFFCompChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
586 
587  i=0;
588  if (opt.outputImageTypeHDR == "exr") {
589  i = 0;
592  } else if (opt.outputImageTypeHDR == "tif") {
593  i = 1;
596  if (opt.outputImageTypeHDRCompression == "PACKBITS") {
597  m_FileFormatHDRTIFFCompChoice->SetSelection(1);
598  } else if (opt.outputImageTypeHDRCompression == "LZW") {
599  m_FileFormatHDRTIFFCompChoice->SetSelection(2);
600  } else if (opt.outputImageTypeHDRCompression == "DEFLATE") {
601  m_FileFormatHDRTIFFCompChoice->SetSelection(3);
602  } else {
603  m_FileFormatHDRTIFFCompChoice->SetSelection(0);
604  }
605  } else
606  wxLogError(wxT("INTERNAL error: unknown hdr output image type"));
607 
608  m_HDRFileFormatChoice->SetSelection(i);
609 
610  m_pano_ctrls->FitInside();
611  Layout();
612  Thaw();
613 
614 #ifdef __WXMSW__
615  this->Refresh(false);
616 #endif
617 }
618 
619 void PanoPanel::ProjectionChanged ( wxCommandEvent & e )
620 {
621  if (updatesDisabled) return;
623 // PanoramaOptions::ProjectionFormat oldP = opt.getProjection();
624 
626 // int w = opt.getWidth();
627 // int h = opt.getHeight();
628  opt.setProjection(newP);
629 
632  );
633  DEBUG_DEBUG ("Projection changed: " << newP)
634 }
635 
636 void PanoPanel::HFOVChanged ( wxCommandEvent & e )
637 {
638  if (updatesDisabled) return;
640 
641 
642  wxString text = m_HFOVText->GetValue();
643  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
644  if (text == wxT("")) {
645  return;
646  }
647 
648  double hfov;
649  if (!hugin_utils::str2double(text, hfov)) {
650  wxLogError(_("Value must be numeric."));
651  return;
652  }
653 
654  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
655  wxLogError(wxString::Format(
656  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
657  opt.getMaxHFOV()));
658  }
659  opt.setHFOV(hfov);
660  // recalculate panorama height...
663  );
664 
665  DEBUG_INFO ( "new hfov: " << hfov )
666 }
667 
668 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
669 {
670  if (updatesDisabled) return;
672 
673  wxString text = m_VFOVText->GetValue();
674  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
675  if (text == wxT("")) {
676  return;
677  }
678 
679  double vfov;
680  if (!hugin_utils::str2double(text, vfov)) {
681  wxLogError(_("Value must be numeric."));
682  return;
683  }
684 
685  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
686  wxLogError(wxString::Format(
687  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
688  opt.getMaxVFOV()));
689  vfov = opt.getMaxVFOV();
690  }
691  opt.setVFOV(vfov);
692  // recalculate panorama height...
695  );
696 
697  DEBUG_INFO ( "new vfov: " << vfov )
698 }
699 
700 /*
701 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
702 {
703  DEBUG_TRACE("")
704  if (updatesDisabled) return;
705  PanoramaOptions opt = pano->getOptions();
706  int vfov = m_VFOVSpin->GetValue() ;
707 
708  if (vfov != opt.getVFOV()) {
709  opt.setVFOV(vfov);
710  GlobalCmdHist::getInstance().addCommand(
711  new PanoCommand::SetPanoOptionsCmd( pano, opt )
712  );
713  DEBUG_INFO ( "new vfov: " << vfov << " => height: " << opt.getHeight() );
714  } else {
715  DEBUG_DEBUG("not setting same fov");
716  }
717 }
718 */
719 
720 void PanoPanel::WidthChanged ( wxCommandEvent & e )
721 {
722  if (updatesDisabled) return;
724  long nWidth;
725  if (m_WidthTxt->GetValue().ToLong(&nWidth)) {
726  if (nWidth <= 0) return;
727  opt.setWidth((unsigned int) nWidth, m_keepViewOnResize);
730  );
731  DEBUG_INFO(nWidth );
732  } else {
733  wxLogError(_("width needs to be an integer bigger than 0"));
734  }
735 }
736 
737 void PanoPanel::HeightChanged ( wxCommandEvent & e )
738 {
739  if (updatesDisabled) return;
741  long nHeight;
742  if (m_HeightTxt->GetValue().ToLong(&nHeight)) {
743  if(nHeight <= 0) return;
744  opt.setHeight((unsigned int) nHeight);
747  );
748  DEBUG_INFO(nHeight);
749  } else {
750  wxLogError(_("height needs to be an integer bigger than 0"));
751  }
752 }
753 
754 void PanoPanel::ROIChanged ( wxCommandEvent & e )
755 {
756  if (updatesDisabled) return;
758  long left, right, top, bottom;
759  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
760  wxLogError(_("Top needs to be an integer bigger than 0"));
761  return;
762  }
763  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
764  wxLogError(_("left needs to be an integer bigger than 0"));
765  return;
766  }
767  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
768  wxLogError(_("right needs to be an integer bigger than 0"));
769  return;
770  }
771  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
772  wxLogError(_("bottom needs to be an integer bigger than 0"));
773  return;
774  }
775  opt.setROI(vigra::Rect2D(left, top, right, bottom));
776 
777  // make sure that left is really to the left of right
778  if(opt.getROI().width()<1) {
779  wxLogError(_("Left boundary must be smaller than right."));
780  UpdateDisplay(pano->getOptions(), false);
781  return;
782  }
783  // make sure that top is really higher than bottom
784  if(opt.getROI().height()<1) {
785  wxLogError(_("Top boundary must be smaller than bottom."));
786  UpdateDisplay(pano->getOptions(), false);
787  return;
788  }
789 
792  );
793 }
794 
795 
796 void PanoPanel::EnableControls(bool enable)
797 {
798 // m_HFOVSpin->Enable(enable);
799 // m_VFOVSpin->Enable(enable);
800  m_WidthTxt->Enable(enable);
801  m_RemapperChoice->Enable(enable);
802  m_BlenderChoice->Enable(enable);
803 // m_CalcHFOVButton->Enable(enable);
804 // m_CalcOptWidthButton->Enable(enable);
805 // m_CalcOptROIButton->Enable(enable);
806 }
807 
808 void PanoPanel::RemapperChanged(wxCommandEvent & e)
809 {
810  int remapper = m_RemapperChoice->GetSelection();
811  DEBUG_DEBUG("changing remapper to " << remapper);
812 
814  if (remapper == 1) {
816  } else {
818  }
819 
822  );
823 }
824 
825 void PanoPanel::OnRemapperOptions(wxCommandEvent & e)
826 {
829  wxDialog dlg;
830  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("nona_options_dialog"));
831  wxChoice * interpol_choice = XRCCTRL(dlg, "nona_choice_interpolator", wxChoice);
832  wxCheckBox * cropped_cb = XRCCTRL(dlg, "nona_save_cropped", wxCheckBox);
833  interpol_choice->SetSelection(opt.interpolator);
834  cropped_cb->SetValue(opt.tiff_saveROI);
835  dlg.CentreOnParent();
836 
837  if (dlg.ShowModal() == wxID_OK) {
838  int interpol = interpol_choice->GetSelection();
839  if (interpol >= 0) {
840  opt.interpolator = (vigra_ext::Interpolator) interpol;
841  }
842  opt.tiff_saveROI = cropped_cb->GetValue();
845  );
846  }
847  } else {
848  wxLogError(_("PTmender options not yet implemented"));
849  }
850 }
851 
852 void PanoPanel::BlenderChanged(wxCommandEvent & e)
853 {
856 
859  );
860 }
861 
862 void PanoPanel::OnBlenderOptions(wxCommandEvent & e)
863 {
866  wxDialog dlg;
867  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("enblend_options_dialog"));
868  wxTextCtrl * enblend_opts_text = XRCCTRL(dlg, "blender_arguments_text", wxTextCtrl);
869  enblend_opts_text->ChangeValue(wxString(opt.enblendOptions.c_str(), wxConvLocal));
870  dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp(wxT("Enblend.html")); }, wxID_HELP);
871  dlg.CentreOnParent();
872 
873  if (dlg.ShowModal() == wxID_OK) {
874  opt.enblendOptions = enblend_opts_text->GetValue().mb_str(wxConvLocal);
877  );
878  }
879  }
880  else
881  {
883  {
884  wxDialog dlg;
885  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("verdandi_options_dialog"));
886  wxChoice * verdandiBlendModeChoice = XRCCTRL(dlg, "verdandi_blend_mode_choice", wxChoice);
887  if (opt.verdandiOptions.find("--seam=blend")!=std::string::npos)
888  {
889  verdandiBlendModeChoice->SetSelection(1);
890  }
891  else
892  {
893  verdandiBlendModeChoice->SetSelection(0);
894  };
895  dlg.CentreOnParent();
896 
897  if (dlg.ShowModal() == wxID_OK)
898  {
899  if (verdandiBlendModeChoice->GetSelection() == 1)
900  {
901  opt.verdandiOptions = "--seam=blend";
902  }
903  else
904  {
905  opt.verdandiOptions = "";
906  };
908  };
909  }
910  else
911  {
912  wxLogError(_("PTblender options not yet implemented"));
913  };
914  };
915 }
916 
917 void PanoPanel::OnEdgeFillChanged(wxCommandEvent & e)
918 {
921  {
922  if (opt.edgeFillMode != newMode)
923  {
924  opt.edgeFillMode = newMode;
927  );
928  };
929  };
930 }
931 
932 void PanoPanel::OnEdgeFillOptions(wxCommandEvent& e)
933 {
935  wxDialog dlg;
936  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("filledge_options_dialog"));
937  wxCheckBox* keepUnfillVersion = XRCCTRL(dlg, "edgefill_save_input", wxCheckBox);
938  keepUnfillVersion->SetValue(opt.keepEdgeFillInput);
939  dlg.CentreOnParent();
940 
941  if (dlg.ShowModal() == wxID_OK)
942  {
943  opt.keepEdgeFillInput = keepUnfillVersion->IsChecked();
945  };
946 }
947 
948 void PanoPanel::FusionChanged(wxCommandEvent & e)
949 {
950  int fusion = m_FusionChoice->GetSelection();
951  DEBUG_DEBUG("changing stacking program to " << fusion);
952 }
953 
954 void PanoPanel::OnFusionOptions(wxCommandEvent & e)
955 {
957  wxDialog dlg;
958  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("enfuse_options_dialog"));
959  wxTextCtrl * enfuse_opts_text = XRCCTRL(dlg, "enfuse_arguments_text", wxTextCtrl);
960  enfuse_opts_text->ChangeValue(wxString(opt.enfuseOptions.c_str(), wxConvLocal));
961  dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp(wxT("Enfuse.html")); }, wxID_HELP);
962  dlg.CentreOnParent();
963 
964  if (dlg.ShowModal() == wxID_OK) {
965  opt.enfuseOptions = enfuse_opts_text->GetValue().mb_str(wxConvLocal);
968  );
969  }
970 }
971 
972 
973 void PanoPanel::HDRMergeChanged(wxCommandEvent & e)
974 {
975  int blender = m_HDRMergeChoice->GetSelection();
976  DEBUG_DEBUG("changing HDR merger to " << blender);
977 }
978 
979 void PanoPanel::OnHDRMergeOptions(wxCommandEvent & e)
980 {
983  HDRMergeOptionsDialog dlg(this);
984  dlg.SetCommandLineArgument(wxString(opt.hdrmergeOptions.c_str(), wxConvLocal));
985  if (dlg.ShowModal() == wxOK)
986  {
987  opt.hdrmergeOptions=dlg.GetCommandLineArgument().mb_str(wxConvLocal);
990  );
991  }
992  } else {
993  wxLogError(_("Options for this HDRMerge program not yet implemented"));
994  }
995 }
996 
997 
998 
999 void PanoPanel::DoCalcFOV(wxCommandEvent & e)
1000 {
1001  DEBUG_TRACE("");
1002  if (pano->getActiveImages().empty()) return;
1003 
1006  fitPano.run();
1007  opt.setHFOV(fitPano.getResultHorizontalFOV());
1009 
1010  DEBUG_INFO ( "hfov: " << opt.getHFOV() << " w: " << opt.getWidth() << " h: " << opt.getHeight() << " => vfov: " << opt.getVFOV() << " before update");
1011 
1014  );
1015 
1017  DEBUG_INFO ( "hfov: " << opt2.getHFOV() << " w: " << opt2.getWidth() << " h: " << opt2.getHeight() << " => vfov: " << opt2.getVFOV() << " after update");
1018 
1019 }
1020 
1021 void PanoPanel::DoCalcOptimalWidth(wxCommandEvent & e)
1022 {
1023  if (pano->getActiveImages().empty()) return;
1024 
1026  double sizeFactor = 1.0;
1027  if (wxGetKeyState(WXK_COMMAND))
1028  {
1029  wxConfigBase::Get()->Read(wxT("/Assistant/panoDownsizeFactor"), &sizeFactor, HUGIN_ASS_PANO_DOWNSIZE_FACTOR);
1030  };
1031 
1033 
1034  if (width > 0) {
1035  opt.setWidth( width );
1038  );
1039  }
1040  DEBUG_INFO ( "new optimal width: " << opt.getWidth() );
1041 }
1042 
1043 
1044 void PanoPanel::DoCalcOptimalROI(wxCommandEvent & e)
1045 {
1046  DEBUG_INFO("Dirty ROI Calc\n");
1047  if (pano->getActiveImages().empty())
1048  {
1049  return;
1050  };
1051 
1052  vigra::Rect2D newROI;
1053  {
1054  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
1055  HuginBase::CalculateOptimalROI cropPano(*pano, &progress);
1056  cropPano.run();
1057  if (cropPano.hasRunSuccessfully())
1058  {
1059  newROI = cropPano.getResultOptimalROI();
1060  };
1061  };
1062 
1063  //set the ROI - fail if the right/bottom is zero, meaning all zero
1064  if(!newROI.isEmpty())
1065  {
1067  opt.setROI(newROI);
1070  );
1071  };
1072 };
1073 
1074 void PanoPanel::DoStitch(const wxString& userDefinedSetting)
1075 {
1076  if (pano->getNrOfImages() == 0) {
1077  return;
1078  }
1079 
1080  if (!CheckGoodSize()) {
1081  // oversized pano and the user no longer wants to stitch.
1082  return;
1083  }
1084  if (!CheckHasImages())
1085  {
1086  // output ROI contains no images
1087  return;
1088  };
1089 
1090  // save project
1091  // copy pto file to temporary file
1092  wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
1093  if(!tempDir.IsEmpty())
1094  if(tempDir.Last()!=wxFileName::GetPathSeparator())
1095  tempDir.Append(wxFileName::GetPathSeparator());
1096  wxString currentPTOfn = wxFileName::CreateTempFileName(tempDir+wxT("huginpto_"));
1097  if(currentPTOfn.empty()) {
1098  wxMessageBox(_("Could not create temporary project file"),_("Error"),
1099  wxCANCEL | wxICON_ERROR,this);
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 == wxT(""))
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(wxT(INSTALL_OSX_BUNDLE_DIR), wxEmptyString);
1121  hugin_stitch_project_app.AppendDir(wxT("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 = wxT("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(), wxT(""),
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  wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
1156 #ifdef __WXMSW__
1157  wxT("Hugin"),
1158 #else
1159  wxT(""),
1160 #endif
1161  wxOK | wxICON_INFORMATION);
1162  if (dlg.ShowModal() != wxID_OK)
1163  {
1164  return;
1165  };
1166  prefix = dlg.GetPath();
1167  };
1168  // check free space
1169  if (!CheckFreeSpace(prefix.GetPath()))
1170  {
1171  return;
1172  };
1173 
1174  wxString switches(wxT(" --delete -o "));
1175  if(wxConfigBase::Get()->Read(wxT("/Processor/overwrite"), HUGIN_PROCESSOR_OVERWRITE) == 1)
1176  switches=wxT(" --overwrite")+switches;
1177  if (!userDefinedSetting.IsEmpty())
1178  {
1179  switches = " --user-defined-output=" + hugin_utils::wxQuoteFilename(userDefinedSetting) + " " + switches;
1180  };
1181  wxString command = hugin_stitch_project + switches + hugin_utils::wxQuoteFilename(dlg.GetPath()) + wxT(" ") + hugin_utils::wxQuoteFilename(currentPTOfn);
1182 
1183  wxConfigBase::Get()->Flush();
1184 #ifdef __WXGTK__
1185  // work around a wxExecute bug/problem
1186  // (endless polling of fd 0 and 1 in hugin_stitch_project)
1187  wxProcess *my_process = new wxProcess(this);
1188  my_process->Redirect();
1189 
1190  // Delete itself once processes terminated.
1191  my_process->Detach();
1192  wxExecute(command,wxEXEC_ASYNC, my_process);
1193 #else
1194  wxExecute(command);
1195 #endif
1197 }
1198 
1199 void PanoPanel::DoSendToBatch(const wxString& userDefinedSetting)
1200 {
1201  if (pano->getNrOfImages() == 0)
1202  {
1203  return;
1204  }
1205 
1206  if (!CheckGoodSize())
1207  {
1208  // oversized pano and the user no longer wants to stitch.
1209  return;
1210  }
1211  if( !CheckHasImages())
1212  {
1213  // output ROI contains no images
1214  return;
1215  };
1216 
1217  wxString switches(wxT(" "));
1218  if (wxConfigBase::Get()->Read(wxT("/Processor/start"), HUGIN_PROCESSOR_START) != 0)
1219  {
1220  switches += wxT("-b ");
1221  };
1222  if (wxConfigBase::Get()->Read(wxT("/Processor/overwrite"), HUGIN_PROCESSOR_OVERWRITE) != 0)
1223  {
1224  switches += wxT("-o ");
1225  };
1226  if (wxConfigBase::Get()->Read(wxT("/Processor/verbose"), HUGIN_PROCESSOR_VERBOSE) != 0)
1227  {
1228  switches += wxT("-v ");
1229  };
1230  if (!userDefinedSetting.IsEmpty())
1231  {
1232  switches += "--user-defined=" + hugin_utils::wxQuoteFilename(userDefinedSetting) + " ";
1233  };
1234  if(pano->isDirty())
1235  {
1236  bool showDlg=wxConfigBase::Get()->Read(wxT("ShowSaveMessage"), 1l)==1;
1237  if(showDlg)
1238  {
1239  // show information that project file needs to be saved first
1240  // and user has to give the output prefix afterwards
1241  wxDialog dlg;
1242  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("stitch_message_dlg"));
1243  if (!(MainFrame::Get()->getProjectName().IsEmpty()))
1244  {
1245  // project file was already saved with a name, adapt message text for this use case
1246  XRCCTRL(dlg, "stitch_message_text", wxStaticText)->SetLabel(
1247  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."),
1248  MainFrame::Get()->getProjectName().c_str()
1249  )
1250  );
1251  };
1252  if(dlg.ShowModal())
1253  {
1254  if(XRCCTRL(dlg, "stitch_dont_show_checkbox", wxCheckBox)->IsChecked())
1255  {
1256  wxConfigBase::Get()->Write(wxT("ShowSaveMessage"), 0l);
1257  };
1258  };
1259  };
1260  wxCommandEvent dummy;
1261  MainFrame::Get()->OnSaveProject(dummy);
1262  //test if save was sucessful
1263  if(pano->isDirty())
1264  {
1265  return;
1266  };
1267  };
1268  wxString projectFile = MainFrame::Get()->getProjectName();
1269  if(wxFileName::FileExists(projectFile))
1270  {
1271  wxFileName outputPrefix(getDefaultOutputName(projectFile, *pano));
1272  outputPrefix.Normalize(wxPATH_NORM_ABSOLUTE | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_SHORTCUT);
1273 
1274  // Show a file save dialog so user can confirm/change the prefix.
1275  // (We don't have to worry about overwriting existing files, since PTBatcherGUI checks this, or the overwrite flag was set.)
1276  wxFileDialog dlg(this,_("Specify output prefix"),
1277  outputPrefix.GetPath(), outputPrefix.GetName(), wxT(""),
1278  wxFD_SAVE, wxDefaultPosition);
1279  if (dlg.ShowModal() != wxID_OK)
1280  {
1281  return;
1282  };
1283  while(containsInvalidCharacters(dlg.GetPath()))
1284  {
1285  wxArrayString list;
1286  list.Add(dlg.GetPath());
1287  ShowFilenameWarning(this, list);
1288  if(dlg.ShowModal()!=wxID_OK)
1289  return;
1290  };
1291  wxFileName prefix(dlg.GetPath());
1292  while (!prefix.IsDirWritable())
1293  {
1294  wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
1295 #ifdef __WXMSW__
1296  wxT("Hugin"),
1297 #else
1298  wxT(""),
1299 #endif
1300  wxOK | wxICON_INFORMATION);
1301  if (dlg.ShowModal() != wxID_OK)
1302  {
1303  return;
1304  };
1305  prefix = dlg.GetPath();
1306  };
1307  // check free space
1308  if (!CheckFreeSpace(prefix.GetPath()))
1309  {
1310  return;
1311  };
1312 
1313 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
1314  wxString cmd = MacGetPathToMainExecutableFileOfRegisteredBundle(CFSTR("net.sourceforge.hugin.PTBatcherGUI"));
1315  if(cmd != wxT(""))
1316  {
1317  //Found PTBatcherGui inside the (registered) PTBatcherGui bundle. Call it directly.
1318  //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
1319  //will provide the menu
1320  cmd = hugin_utils::wxQuoteString(cmd);
1321  cmd += wxT(" ") + switches + hugin_utils::wxQuoteFilename(projectFile) + wxT(" ") + hugin_utils::wxQuoteFilename(dlg.GetPath());
1322  wxExecute(cmd);
1323  }
1324  else
1325  { //Can't find PTBatcherGui.app bundle. Use the most straightforward call possible to the bundle but this should actually not work either.
1326  wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
1327  cmd = wxT("open -b net.sourceforge.hugin.PTBatcherGUI ")+hugin_utils::wxQuoteFilename(projectFile);
1328  wxExecute(cmd);
1329  }
1330 
1331 #else
1332  const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
1333  wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("PTBatcherGUI ") + switches + hugin_utils::wxQuoteFilename(projectFile) + wxT(" ") + hugin_utils::wxQuoteFilename(dlg.GetPath()));
1334 #endif
1336  }
1337 };
1338 
1339 void PanoPanel::DoUserDefinedStitch(const wxString& settings)
1340 {
1341  if (pano->getNrOfImages() == 0)
1342  {
1343  return;
1344  }
1345 
1346  if (!CheckGoodSize())
1347  {
1348  // oversized pano and the user no longer wants to stitch.
1349  return;
1350  }
1351  if (!CheckHasImages())
1352  {
1353  // output ROI contains no images
1354  return;
1355  };
1356  wxFileName userOutputSequence;
1357  if (settings.IsEmpty())
1358  {
1359  // no filename given, ask user
1360  wxConfigBase* config = wxConfigBase::Get();
1361  wxString path = config->Read(wxT("/userDefinedOutputPath"), MainFrame::Get()->GetDataPath());
1362  wxFileDialog userOutputDlg(this, _("Select user defined output"),
1363  path, wxT(""), _("User defined output|*.executor"),
1364  wxFD_OPEN | wxFD_FILE_MUST_EXIST, wxDefaultPosition);
1365  if (userOutputDlg.ShowModal() != wxID_OK)
1366  {
1367  return;
1368  };
1369  // remember path for later
1370  config->Write(wxT("/userDefinedOutputPath"), userOutputDlg.GetDirectory());
1371  userOutputSequence = userOutputDlg.GetPath();
1372  }
1373  else
1374  {
1375  //filename given, check existance
1376  userOutputSequence = settings;
1377  if (!userOutputSequence.Exists())
1378  {
1379  wxMessageBox(wxString::Format(wxT("User defined output %s not found.\nStopping processing."), userOutputSequence.GetFullPath()), _("Warning"), wxOK | wxICON_INFORMATION);
1380  return;
1381  };
1382  };
1383  DoStitchOrSendBatch(userOutputSequence.GetFullPath());
1384 }
1385 
1386 void PanoPanel::DoStitchOrSendBatch(const wxString& userDefinedSetting)
1387 {
1388  long t;
1389  if(wxGetKeyState(WXK_COMMAND))
1390  {
1391  t=1;
1392  }
1393  else
1394  {
1395  wxConfigBase::Get()->Read(wxT("/Processor/gui"), &t, HUGIN_PROCESSOR_GUI);
1396  };
1397  switch (t)
1398  {
1399  // PTBatcher
1400  case 0:
1401  DoSendToBatch(userDefinedSetting);
1402  break;
1403  // hugin_stitch_project
1404  case 1:
1405  DoStitch(userDefinedSetting);
1406  break;
1407  // there is an error in the preferences
1408  default :
1409  // TODO: notify user and fix preferences misconfiguration
1410  break;
1411  }
1412 }
1413 
1414 void PanoPanel::OnDoStitch(wxCommandEvent& e)
1415 {
1417 }
1418 
1419 void PanoPanel::FileFormatChanged(wxCommandEvent & e)
1420 {
1421 
1422  int fmt = m_FileFormatChoice->GetSelection();
1423  DEBUG_DEBUG("changing file format to " << fmt);
1424 
1426  switch (fmt) {
1427  case 1:
1428  opt.outputImageType ="jpg";
1429  break;
1430  case 2:
1431  opt.outputImageType ="png";
1432  break;
1433  case 3:
1434  opt.outputImageType ="exr";
1435  break;
1436  default:
1437  case 0:
1438  opt.outputImageType ="tif";
1439  break;
1440  }
1441 
1444  );
1445 }
1446 
1447 void PanoPanel::HDRFileFormatChanged(wxCommandEvent & e)
1448 {
1449 
1450  int fmt = m_HDRFileFormatChoice->GetSelection();
1451  DEBUG_DEBUG("changing file format to " << fmt);
1452 
1454  switch (fmt) {
1455  case 1:
1456  opt.outputImageTypeHDR ="tif";
1457  break;
1458  default:
1459  case 0:
1460  opt.outputImageTypeHDR ="exr";
1461  break;
1462  }
1463 
1466  );
1467 }
1468 
1469 void PanoPanel::OnJPEGQualityText(wxCommandEvent & e)
1470 {
1472  long l = 100;
1473  m_FileFormatJPEGQualityText->GetValue().ToLong(&l);
1474  if (l < 0) l=1;
1475  if (l > 100) l=100;
1476  DEBUG_DEBUG("Setting jpeg quality to " << l);
1477  opt.quality = l;
1480  );
1481 }
1482 
1483 void PanoPanel::OnNormalTIFFCompression(wxCommandEvent & e)
1484 {
1486  switch(e.GetSelection()) {
1487  case 0:
1488  default:
1489  opt.outputImageTypeCompression = "NONE";
1490  opt.tiffCompression = "NONE";
1491  break;
1492  case 1:
1493  opt.outputImageTypeCompression = "PACKBITS";
1494  opt.tiffCompression = "PACKBITS";
1495  break;
1496  case 2:
1497  opt.outputImageTypeCompression = "LZW";
1498  opt.tiffCompression = "LZW";
1499  break;
1500  case 3:
1501  opt.outputImageTypeCompression = "DEFLATE";
1502  opt.tiffCompression = "DEFLATE";
1503  break;
1504  }
1507  );
1508 }
1509 
1510 void PanoPanel::OnHDRTIFFCompression(wxCommandEvent & e)
1511 {
1513  switch(e.GetSelection()) {
1514  case 0:
1515  default:
1516  opt.outputImageTypeHDRCompression = "NONE";
1517  break;
1518  case 1:
1519  opt.outputImageTypeHDRCompression = "PACKBITS";
1520  break;
1521  case 2:
1522  opt.outputImageTypeHDRCompression = "LZW";
1523  break;
1524  case 3:
1525  opt.outputImageTypeHDRCompression = "DEFLATE";
1526  break;
1527  }
1530  );
1531 }
1532 
1533 void PanoPanel::OnOutputFilesChanged(wxCommandEvent & e)
1534 {
1535  int id = e.GetId();
1537 
1538  if (id == XRCID("pano_cb_ldr_output_blended") ) {
1539  opts.outputLDRBlended = e.IsChecked();
1540  } else if (id == XRCID("pano_cb_ldr_output_layers") ) {
1541  opts.outputLDRLayers = e.IsChecked();
1542  } else if (id == XRCID("pano_cb_ldr_output_exposure_layers") ) {
1543  opts.outputLDRExposureLayers = e.IsChecked();
1544  } else if (id == XRCID("pano_cb_ldr_output_exposure_blended") ) {
1545  opts.outputLDRExposureBlended = e.IsChecked();
1546  } else if (id == XRCID("pano_cb_ldr_output_exposure_layers_fused") ) {
1547  opts.outputLDRExposureLayersFused = e.IsChecked();
1548  } else if (id == XRCID("pano_cb_ldr_output_exposure_remapped") ) {
1549  opts.outputLDRExposureRemapped = e.IsChecked();
1550  } else if (id == XRCID("pano_cb_ldr_output_stacks") ) {
1551  opts.outputLDRStacks = e.IsChecked();
1552  } else if (id == XRCID("pano_cb_hdr_output_blended") ) {
1553  opts.outputHDRBlended = e.IsChecked();
1554  } else if (id == XRCID("pano_cb_hdr_output_stacks") ) {
1555  opts.outputHDRStacks = e.IsChecked();
1556  } else if (id == XRCID("pano_cb_hdr_output_layers") ) {
1557  opts.outputHDRLayers = e.IsChecked();
1558  }
1559 
1561  new PanoCommand::SetPanoOptionsCmd( *pano, opts )
1562  );
1563 }
1564 
1566 {
1568  const vigra::Rect2D cropped_region (opts.getROI());
1569  // width and height of jpeg images has to be smaller than 65500 pixel
1570  if (opts.outputImageType == "jpg" &&
1571  (opts.outputLDRBlended || opts.outputLDRExposureBlended || opts.outputLDRExposureLayersFused) &&
1572  (cropped_region.width()>65500 || cropped_region.height()>65500)
1573  )
1574  {
1575  wxMessageBox(
1576  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()),
1577 #ifdef _WIN32
1578  _("Hugin"),
1579 #else
1580  wxT(""),
1581 #endif
1582  wxICON_EXCLAMATION | wxOK);
1583  return false;
1584  };
1585  wxString message;
1586  const unsigned long long area = (static_cast<unsigned long long>(cropped_region.width()) * cropped_region.height());
1587  // Argh, more than half a gigapixel!
1588  if (area > 500000000)
1589  {
1590  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."),
1591  area / 1000000000.0);
1592  }
1593  else
1594  {
1595  if (cropped_region.width() > 32700 || cropped_region.height() > 32700)
1596  {
1597  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.");
1598  };
1599  };
1600  if (!message.empty())
1601  {
1602  // Tell the user the stitch will be really big, and give them a
1603  // chance to reduce the size.
1604  wxMessageDialog dialog(this,
1605  _("Are you sure you want to stitch such a large panorama?"),
1606 #ifdef _WIN32
1607  _("Hugin"),
1608 #else
1609  wxT(""),
1610 #endif
1611  wxICON_EXCLAMATION | wxYES_NO);
1612  dialog.SetExtendedMessage(message);
1613  dialog.SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
1614  switch (dialog.ShowModal())
1615  {
1616  case wxID_OK:
1617  case wxID_YES:
1618  // Continue stitch.
1619  return true;
1620  break;
1621  default:
1622  // bring the user towards the approptiate controls.
1623  MainFrame* mainframe = MainFrame::Get();
1624  if (!mainframe->IsShown())
1625  {
1626  mainframe->Show();
1627  }
1628  mainframe->ShowStitcherTab();
1629  return false;
1630  }
1631  }
1632  // I see nothing wrong with this...
1633  return true;
1634 }
1635 
1637 {
1639  if(images.empty())
1640  {
1641  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."),
1642 #ifdef _WIN32
1643  _("Hugin"),
1644 #else
1645  wxT(""),
1646 #endif
1647  wxOK | wxICON_INFORMATION);
1648  };
1649  return !images.empty();
1650 };
1651 
1652 bool PanoPanel::CheckFreeSpace(const wxString& folder)
1653 {
1654  wxLongLong freeSpace;
1655  if (wxGetDiskSpace(folder, NULL, &freeSpace))
1656  {
1657  // 4 channels, 16 bit per channel, assuming the we need the 10 fold space for all temporary space
1658  if (pano->getOptions().getROI().area() * 80 > freeSpace)
1659  {
1660  wxMessageDialog dialog(this,
1661  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),
1662 #ifdef _WIN32
1663  _("Hugin"),
1664 #else
1665  wxT(""),
1666 #endif
1667  wxICON_EXCLAMATION | wxYES_NO);
1668  dialog.SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
1669  if (dialog.ShowModal() == wxID_NO)
1670  {
1671  // bring the user towards the approptiate controls.
1672  MainFrame* mainframe = MainFrame::Get();
1673  if (!mainframe->IsShown())
1674  {
1675  mainframe->Show();
1676  }
1677  mainframe->ShowStitcherTab();
1678  return false;
1679  };
1680  };
1681  };
1682  return true;
1683 };
1684 
1686 {
1687  m_guiLevel=newGuiLevel;
1688  UpdateDisplay(m_oldOpt, false);
1689 };
1690 
1692 
1694  : wxXmlResourceHandler()
1695 {
1696  AddWindowStyles();
1697 }
1698 
1700 {
1701  XRC_MAKE_INSTANCE(cp, PanoPanel)
1702 
1703  cp->Create(m_parentAsWindow,
1704  GetID(),
1705  GetPosition(), GetSize(),
1706  GetStyle(wxT("style")),
1707  GetName());
1708 
1709  SetupWindow( cp);
1710 
1711  return cp;
1712 }
1713 
1714 bool PanoPanelXmlHandler::CanHandle(wxXmlNode *node)
1715 {
1716  return IsOfClass(node, wxT("PanoPanel"));
1717 }
1718 
1719 IMPLEMENT_DYNAMIC_CLASS(PanoPanelXmlHandler, wxXmlResourceHandler)
1720 
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:1636
void OnBlenderOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:862
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:852
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:737
declaration of functions to handle stacks and layers
void DoStitch(const wxString &userDefinedSetting=wxEmptyString)
stitching using hugin_stitch_project
Definition: PanoPanel.cpp:1074
void OnNormalTIFFCompression(wxCommandEvent &e)
Definition: PanoPanel.cpp:1483
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:1652
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:796
int roundi(T x)
Definition: hugin_math.h:73
wxTextCtrl * m_ROITopTxt
Definition: PanoPanel.h:198
void DoCalcFOV(wxCommandEvent &e)
Definition: PanoPanel.cpp:999
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void ProjectionChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:619
void ROIChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:754
virtual ~PanoPanel(void)
Definition: PanoPanel.cpp:257
bool outputLDRLayers
save remapped layers (LDR)
virtual wxObject * DoCreateResource()
Definition: PanoPanel.cpp:1699
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:954
#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:917
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:1339
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:1685
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:825
bool outputLDRExposureBlended
&lt; save exposure fused stacks (no exposure adjustment)
void VFOVChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:668
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:808
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:1510
static GlobalCmdHist & getInstance()
void OnEdgeFillOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:932
void FileFormatChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:1419
#define HUGIN_PROCESSOR_START
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
void FusionChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:948
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:720
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:1469
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:636
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:1044
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:1021
void HDRFileFormatChanged(wxCommandEvent &e)
Definition: PanoPanel.cpp:1447
#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:1199
#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:1386
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:1565
Define the pano edit panel.
Definition: PanoPanel.h:43
void OnHDRMergeOptions(wxCommandEvent &e)
Definition: PanoPanel.cpp:979
virtual bool CanHandle(wxXmlNode *node)
Definition: PanoPanel.cpp:1714
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:973
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:1533
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:1414
bool StackCheck(HuginBase::Panorama &pano)
Definition: PanoPanel.cpp:296
wxTextCtrl * m_ROIRightTxt
Definition: PanoPanel.h:197