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