PanoPanel.cpp

Go to the documentation of this file.
00001 // -*- c-basic-offset: 4 -*-
00002 
00028 #include "hugin_config.h"
00029 #include <wx/stdpaths.h>
00030 
00031 #include "panoinc_WX.h"
00032 #include "panoinc.h"
00033 #include "base_wx/platform.h"
00034 #include "base_wx/PanoCommand.h"
00035 
00036 #include <hugin/config_defaults.h>
00037 
00038 #include "nona/Stitcher.h"
00039 #include "base_wx/wxPlatform.h"
00040 
00041 extern "C" {
00042 #include <pano13/queryfeature.h>
00043 }
00044 
00045 #include "base_wx/CommandHistory.h"
00046 #include "hugin/CPImageCtrl.h"
00047 #include "hugin/CPImagesComboBox.h"
00048 #include "hugin/PanoPanel.h"
00049 #include "hugin/MainFrame.h"
00050 #include "hugin/huginApp.h"
00051 #include "hugin/HDRMergeOptionDialog.h"
00052 #include "hugin/TextKillFocusHandler.h"
00053 #include "base_wx/MyProgressDialog.h"
00054 #include "hugin/config_defaults.h"
00055 #include "base_wx/platform.h"
00056 #include "base_wx/huginConfig.h"
00057 #include "base_wx/LensTools.h"
00058 #include "algorithms/basic/LayerStacks.h"
00059 #include "algorithms/basic/CalculateOptimalScale.h"
00060 #include "algorithms/basic/CalculateOptimalROI.h"
00061 #include "algorithms/nona/FitPanorama.h"
00062 #include "lensdb/LensDB.h"
00063 
00064 #define WX_BROKEN_SIZER_UNKNOWN
00065 
00066 BEGIN_EVENT_TABLE(PanoPanel, wxPanel)
00067     EVT_CHOICE ( XRCID("pano_choice_pano_type"),PanoPanel::ProjectionChanged )
00068     EVT_TEXT_ENTER( XRCID("pano_text_hfov"),PanoPanel::HFOVChanged )
00069     EVT_TEXT_ENTER( XRCID("pano_text_vfov"),PanoPanel::VFOVChanged )
00070     EVT_BUTTON ( XRCID("pano_button_calc_fov"), PanoPanel::DoCalcFOV)
00071     EVT_TEXT_ENTER ( XRCID("pano_val_width"),PanoPanel::WidthChanged )
00072     EVT_TEXT_ENTER ( XRCID("pano_val_height"),PanoPanel::HeightChanged )
00073     EVT_TEXT_ENTER ( XRCID("pano_val_roi_top"),PanoPanel::ROIChanged )
00074     EVT_TEXT_ENTER ( XRCID("pano_val_roi_bottom"),PanoPanel::ROIChanged )
00075     EVT_TEXT_ENTER ( XRCID("pano_val_roi_left"),PanoPanel::ROIChanged )
00076     EVT_TEXT_ENTER ( XRCID("pano_val_roi_right"),PanoPanel::ROIChanged )
00077     EVT_BUTTON ( XRCID("pano_button_opt_width"), PanoPanel::DoCalcOptimalWidth)
00078     EVT_BUTTON ( XRCID("pano_button_opt_roi"), PanoPanel::DoCalcOptimalROI)
00079     EVT_BUTTON ( XRCID("pano_button_stitch"),PanoPanel::OnDoStitch )
00080 
00081     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_blended"), PanoPanel::OnOutputFilesChanged)
00082     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_layers"), PanoPanel::OnOutputFilesChanged)
00083     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_exposure_layers"), PanoPanel::OnOutputFilesChanged)
00084     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_exposure_blended"), PanoPanel::OnOutputFilesChanged)
00085     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_exposure_layers_fused"), PanoPanel::OnOutputFilesChanged)
00086     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_stacks"), PanoPanel::OnOutputFilesChanged)
00087     EVT_CHECKBOX ( XRCID("pano_cb_ldr_output_exposure_remapped"), PanoPanel::OnOutputFilesChanged)
00088     EVT_CHECKBOX ( XRCID("pano_cb_hdr_output_blended"), PanoPanel::OnOutputFilesChanged)
00089     EVT_CHECKBOX ( XRCID("pano_cb_hdr_output_stacks"), PanoPanel::OnOutputFilesChanged)
00090     EVT_CHECKBOX ( XRCID("pano_cb_hdr_output_layers"), PanoPanel::OnOutputFilesChanged)
00091 
00092     EVT_CHOICE ( XRCID("pano_choice_remapper"),PanoPanel::RemapperChanged )
00093     EVT_BUTTON ( XRCID("pano_button_remapper_opts"),PanoPanel::OnRemapperOptions )
00094 
00095     EVT_CHOICE ( XRCID("pano_choice_fusion"),PanoPanel::FusionChanged )
00096     EVT_BUTTON ( XRCID("pano_button_fusion_opts"),PanoPanel::OnFusionOptions )
00097 
00098     EVT_CHOICE ( XRCID("pano_choice_hdrmerge"),PanoPanel::HDRMergeChanged )
00099     EVT_BUTTON ( XRCID("pano_button_hdrmerge_opts"),PanoPanel::OnHDRMergeOptions )
00100 
00101     EVT_CHOICE ( XRCID("pano_choice_blender"),PanoPanel::BlenderChanged )
00102     EVT_BUTTON ( XRCID("pano_button_blender_opts"),PanoPanel::OnBlenderOptions )
00103 
00104     EVT_CHOICE ( XRCID("pano_choice_file_format"),PanoPanel::FileFormatChanged )
00105     EVT_CHOICE ( XRCID("pano_choice_hdr_file_format"),PanoPanel::HDRFileFormatChanged )
00106 //    EVT_SPINCTRL ( XRCID("pano_output_normal_opts_jpeg_quality"),PanoPanel::OnJPEGQualitySpin )
00107     EVT_TEXT_ENTER ( XRCID("pano_output_normal_opts_jpeg_quality"),PanoPanel::OnJPEGQualityText )
00108     EVT_CHOICE ( XRCID("pano_output_normal_opts_tiff_compression"),PanoPanel::OnNormalTIFFCompression)
00109     EVT_CHOICE ( XRCID("pano_output_hdr_opts_tiff_compression"),PanoPanel::OnHDRTIFFCompression)
00110 
00111 END_EVENT_TABLE()
00112 
00113 PanoPanel::PanoPanel()
00114     : pano(0), m_guiLevel(GUI_SIMPLE), updatesDisabled(false)
00115 {
00116 
00117 }
00118 
00119 bool PanoPanel::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
00120                       long style, const wxString& name)
00121 {
00122     if (! wxPanel::Create(parent, id, pos, size, style, name)) {
00123         return false;
00124     }
00125 
00126     wxXmlResource::Get()->LoadPanel(this, wxT("panorama_panel"));
00127     wxPanel * panel = XRCCTRL(*this, "panorama_panel", wxPanel);
00128 
00129     wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
00130     topsizer->Add(panel, 1, wxEXPAND, 0);
00131     SetSizer(topsizer);
00132 
00133     // converts KILL_FOCUS events to usable TEXT_ENTER events
00134     // get gui controls
00135     m_ProjectionChoice = XRCCTRL(*this, "pano_choice_pano_type" ,wxChoice);
00136     DEBUG_ASSERT(m_ProjectionChoice);
00137 
00138     m_keepViewOnResize = true;
00139     m_hasStacks=false;
00140 
00141 #ifdef ThisNeverHappens
00142 // provide some translatable strings for the drop down menu
00143     wxLogMessage(_("Fisheye"));
00144     wxLogMessage(_("Stereographic"));
00145     wxLogMessage(_("Mercator"));
00146     wxLogMessage(_("Trans Mercator"));
00147     wxLogMessage(_("Sinusoidal"));
00148     wxLogMessage(_("Lambert Cylindrical Equal Area"));
00149     wxLogMessage(_("Lambert Equal Area Azimuthal"));
00150     wxLogMessage(_("Albers Equal Area Conic"));
00151     wxLogMessage(_("Miller Cylindrical"));
00152     wxLogMessage(_("Panini"));
00153     wxLogMessage(_("Architectural"));
00154     wxLogMessage(_("Orthographic"));
00155     wxLogMessage(_("Equisolid"));
00156     wxLogMessage(_("Equirectangular Panini"));
00157     wxLogMessage(_("Biplane"));
00158     wxLogMessage(_("Triplane"));
00159     wxLogMessage(_("Panini General"));
00160     wxLogMessage(_("Thoby Projection"));
00161     wxLogMessage(_("Hammer-Aitoff Equal Area"));
00162 #endif
00163 
00164     /* populate with all available projection types */
00165     int nP = panoProjectionFormatCount();
00166     for(int n=0; n < nP; n++) {
00167         pano_projection_features proj;
00168         if (panoProjectionFeaturesQuery(n, &proj)) {
00169             wxString str2(proj.name, wxConvLocal);
00170             m_ProjectionChoice->Append(wxGetTranslation(str2));
00171         }
00172     }
00173     m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
00174     DEBUG_ASSERT(m_HFOVText);
00175     m_CalcHFOVButton = XRCCTRL(*this, "pano_button_calc_fov" ,wxButton);
00176     DEBUG_ASSERT(m_CalcHFOVButton);
00177     m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
00178     m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
00179     DEBUG_ASSERT(m_VFOVText);
00180     m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
00181 
00182 
00183     m_WidthTxt = XRCCTRL(*this, "pano_val_width", wxTextCtrl);
00184     DEBUG_ASSERT(m_WidthTxt);
00185     m_WidthTxt->PushEventHandler(new TextKillFocusHandler(this));
00186     m_CalcOptWidthButton = XRCCTRL(*this, "pano_button_opt_width" ,wxButton);
00187     DEBUG_ASSERT(m_CalcOptWidthButton);
00188 
00189     m_HeightTxt = XRCCTRL(*this, "pano_val_height", wxTextCtrl);
00190     DEBUG_ASSERT(m_HeightTxt);
00191     m_HeightTxt->PushEventHandler(new TextKillFocusHandler(this));
00192 
00193     m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
00194     DEBUG_ASSERT(m_ROILeftTxt);
00195     m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
00196 
00197     m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
00198     DEBUG_ASSERT(m_ROIRightTxt);
00199     m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
00200 
00201     m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
00202     DEBUG_ASSERT(m_ROITopTxt);
00203     m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
00204 
00205     m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
00206     DEBUG_ASSERT(m_ROIBottomTxt);
00207     m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
00208     
00209     m_CalcOptROIButton = XRCCTRL(*this, "pano_button_opt_roi" ,wxButton);
00210     DEBUG_ASSERT(m_CalcOptROIButton);    
00211 
00212     m_RemapperChoice = XRCCTRL(*this, "pano_choice_remapper", wxChoice);
00213     DEBUG_ASSERT(m_RemapperChoice);
00214     m_FusionChoice = XRCCTRL(*this, "pano_choice_fusion", wxChoice);
00215     DEBUG_ASSERT(m_FusionChoice);
00216     m_HDRMergeChoice = XRCCTRL(*this, "pano_choice_hdrmerge", wxChoice);
00217     DEBUG_ASSERT(m_HDRMergeChoice);
00218     m_BlenderChoice = XRCCTRL(*this, "pano_choice_blender", wxChoice);
00219     DEBUG_ASSERT(m_BlenderChoice);
00220     FillBlenderList(m_BlenderChoice);
00221 
00222     m_StitchButton = XRCCTRL(*this, "pano_button_stitch", wxButton);
00223     DEBUG_ASSERT(m_StitchButton);
00224 
00225     m_FileFormatChoice = XRCCTRL(*this, "pano_choice_file_format", wxChoice);
00226     DEBUG_ASSERT(m_FileFormatChoice);
00227     m_FileFormatOptionsLabel = XRCCTRL(*this, "pano_output_ldr_format_options_label", wxStaticText);
00228     
00229     m_FileFormatJPEGQualityText = XRCCTRL(*this, "pano_output_normal_opts_jpeg_quality", wxTextCtrl);
00230     DEBUG_ASSERT(m_FileFormatJPEGQualityText);
00231     m_FileFormatJPEGQualityText->PushEventHandler(new TextKillFocusHandler(this));
00232 
00233     m_FileFormatTIFFCompChoice = XRCCTRL(*this, "pano_output_normal_opts_tiff_compression", wxChoice);
00234     DEBUG_ASSERT(m_FileFormatTIFFCompChoice);
00235 
00236     m_HDRFileFormatChoice = XRCCTRL(*this, "pano_choice_hdr_file_format", wxChoice);
00237     DEBUG_ASSERT(m_HDRFileFormatChoice);
00238     m_HDRFileFormatLabelTIFFCompression = XRCCTRL(*this, "pano_output_hdr_opts_tiff_compression_label", wxStaticText);
00239     DEBUG_ASSERT(m_HDRFileFormatLabelTIFFCompression);
00240     m_FileFormatHDRTIFFCompChoice = XRCCTRL(*this, "pano_output_hdr_opts_tiff_compression", wxChoice);
00241     DEBUG_ASSERT(m_FileFormatHDRTIFFCompChoice);
00242 
00243     m_pano_ctrls = XRCCTRL(*this, "pano_controls_panel", wxScrolledWindow);
00244     DEBUG_ASSERT(m_pano_ctrls);
00245     m_pano_ctrls->SetSizeHints(20, 20);
00246     m_pano_ctrls->FitInside();
00247     m_pano_ctrls->SetScrollRate(10, 10);
00248 
00249 
00250 /*
00251     // trigger creation of apropriate stitcher control, if
00252     // not already happend.
00253     if (! m_Stitcher) {
00254         wxCommandEvent dummy;
00255         StitcherChanged(dummy);
00256     }
00257 */
00258     DEBUG_TRACE("")
00259     return true;
00260 }
00261 
00262 void PanoPanel::Init(HuginBase::Panorama * panorama)
00263 {
00264     pano = panorama;
00265     // observe the panorama
00266     pano->addObserver(this);
00267     panoramaChanged(*panorama);
00268 }
00269 
00270 PanoPanel::~PanoPanel(void)
00271 {
00272     DEBUG_TRACE("dtor");
00273     wxConfigBase::Get()->Write(wxT("Stitcher/DefaultRemapper"),m_RemapperChoice->GetSelection());
00274 
00275     m_HFOVText->PopEventHandler(true);
00276     m_VFOVText->PopEventHandler(true);
00277     m_WidthTxt->PopEventHandler(true);
00278     m_HeightTxt->PopEventHandler(true);
00279     m_ROILeftTxt->PopEventHandler(true);
00280     m_ROIRightTxt->PopEventHandler(true);
00281     m_ROITopTxt->PopEventHandler(true);
00282     m_ROIBottomTxt->PopEventHandler(true);
00283     m_FileFormatJPEGQualityText->PopEventHandler(true);
00284     pano->removeObserver(this);
00285     DEBUG_TRACE("dtor end");
00286 }
00287 
00288 
00289 void PanoPanel::panoramaChanged (HuginBase::Panorama &pano)
00290 {
00291     DEBUG_TRACE("");
00292 
00293 #ifdef STACK_CHECK //Disabled for 0.7.0 release
00294     const bool hasStacks = StackCheck(pano);
00295 #else
00296     const bool hasStacks = false;
00297 #endif
00298 
00299     HuginBase::PanoramaOptions opt = pano.getOptions();
00300 
00301     // update all options for dialog and notebook tab
00302     UpdateDisplay(opt,hasStacks);
00303 
00304     m_oldOpt = opt;
00305 }
00306 
00307 
00308 bool PanoPanel::StackCheck(HuginBase::Panorama &pano)
00309 {
00310     DEBUG_TRACE("");
00311     HuginBase::PanoramaOptions opt = pano.getOptions();
00312 
00313     // Determine if there are stacks in the pano.
00314     HuginBase::UIntSet activeImages = pano.getActiveImages();
00315     HuginBase::UIntSet images = getImagesinROI(pano, activeImages);
00316     std::vector<HuginBase::UIntSet> hdrStacks = HuginBase::getHDRStacks(pano, images, pano.getOptions());
00317     DEBUG_DEBUG(hdrStacks.size() << ": HDR stacks detected");
00318     const bool hasStacks = (hdrStacks.size() != activeImages.size());
00319 
00320     // Only change the output types if the stack configuration has changed.
00321     bool isChanged = (hasStacks != m_hasStacks);
00322     if (isChanged) {
00323         if (hasStacks) {
00324             // Disable normal output formats
00325             opt.outputLDRBlended = false;
00326             opt.outputLDRLayers = false;
00327             // Ensure at least one fused output is enabled
00328             if (!(opt.outputLDRExposureBlended ||
00329                   opt.outputLDRExposureLayers ||
00330                   opt.outputLDRExposureRemapped ||
00331                   opt.outputHDRBlended ||
00332                   opt.outputHDRStacks ||
00333                   opt.outputHDRLayers)) {
00334                 opt.outputLDRExposureBlended = true;
00335             }
00336         } else {
00337             // Disable fused output formats
00338             opt.outputLDRExposureBlended = false;
00339             opt.outputLDRExposureLayers = false;
00340             opt.outputLDRExposureRemapped = false;
00341             opt.outputHDRBlended = false;
00342             opt.outputHDRStacks = false;
00343             opt.outputHDRLayers = false;
00344             // Ensure at least one normal output is enabled
00345             if (!(opt.outputLDRBlended || opt.outputLDRLayers)) {
00346                 opt.outputLDRBlended = true;
00347             }
00348         }
00349         pano.setOptions(opt);
00350     }
00351         
00352     m_hasStacks = hasStacks;
00353 
00354     return hasStacks;
00355 }
00356 
00357 
00358 void PanoPanel::UpdateDisplay(const HuginBase::PanoramaOptions & opt, const bool hasStacks)
00359 {
00360     Freeze();
00361 //    m_HFOVSpin->SetRange(1,opt.getMaxHFOV());
00362 //    m_VFOVSpin->SetRange(1,opt.getMaxVFOV());
00363 
00364     m_ProjectionChoice->SetSelection(opt.getProjection());
00365     m_keepViewOnResize = opt.fovCalcSupported(opt.getProjection());
00366 
00367     std::string val;
00368     val = hugin_utils::doubleToString(opt.getHFOV(),1);
00369     m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
00370     val = hugin_utils::doubleToString(opt.getVFOV(), 1);
00371     m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
00372 
00373     // disable VFOV edit field, due to bugs in setHeight(), setWidth()
00374     bool hasImages = pano->getActiveImages().size() > 0;
00375     m_VFOVText->Enable(m_keepViewOnResize);
00376     m_CalcOptWidthButton->Enable(m_keepViewOnResize && hasImages);
00377     m_CalcHFOVButton->Enable(m_keepViewOnResize && hasImages);
00378     m_CalcOptROIButton->Enable(hasImages);
00379 
00380     m_WidthTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getWidth()));
00381     m_HeightTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getHeight()));
00382 
00383     m_ROILeftTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getROI().left() ));
00384     m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getROI().right() ));
00385     m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getROI().top() ));
00386     m_ROIBottomTxt->ChangeValue(wxString::Format(wxT("%d"), opt.getROI().bottom() ));
00387     {
00388         // format text for display of canvas dimension
00389         wxString label = wxString::Format(wxT("%d x %d"), opt.getROI().width(), opt.getROI().height());
00390         if (opt.getROI().area() >= 20000000)
00391         {
00392             label.Append(wxString::Format(wxT("=%.0f MP"), opt.getROI().area() / 1000000.0));
00393         }
00394         else
00395         {
00396             label.Append(wxString::Format(wxT("=%.1f MP"), opt.getROI().area() / 1000000.0));
00397         };
00398         if (opt.getROI().area() > 0)
00399         {
00400             float ratio = 1.0f*opt.getROI().width() / opt.getROI().height();
00401             if (ratio > 1.0f)
00402             {
00403                 bool handled = false;
00404                 for (unsigned int i = 1; i < 10; ++i)
00405                 {
00406                     if (fabs(i*ratio - hugin_utils::roundi(i*ratio)) < 1e-2)
00407                     {
00408                         label.Append(wxString::Format(wxT(", %d:%d"), hugin_utils::roundi(i*ratio), i));
00409                         handled = true;
00410                         break;
00411                     }
00412                 };
00413                 if (!handled)
00414                 {
00415                     label.Append(wxString::Format(wxT(", %.2f:1"), ratio));
00416                 };
00417             }
00418             else
00419             {
00420                 ratio = 1.0f / ratio;
00421                 bool handled = false;
00422                 for (unsigned int i = 1; i < 10; ++i)
00423                 {
00424                     if (fabs(i*ratio - hugin_utils::roundi(i*ratio)) < 1e-2)
00425                     {
00426                         label.Append(wxString::Format(wxT(", %d:%d"), i, hugin_utils::roundi(i*ratio)));
00427                         handled = true;
00428                         break;
00429                     }
00430                 };
00431                 if (!handled)
00432                 {
00433                     label.Append(wxString::Format(wxT(", 1:%.2f"), ratio));
00434                 };
00435             };
00436         };
00437         XRCCTRL(*this, "pano_size_label", wxStaticText)->SetLabel(label);
00438     };
00439 
00440     // output types
00441     XRCCTRL(*this, "pano_cb_ldr_output_blended", wxCheckBox)->SetValue(opt.outputLDRBlended);
00442     XRCCTRL(*this, "pano_cb_ldr_output_exposure_blended", wxCheckBox)->SetValue(opt.outputLDRExposureBlended);
00443     XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers_fused", wxCheckBox)->SetValue(opt.outputLDRExposureLayersFused);
00444     XRCCTRL(*this, "pano_cb_hdr_output_blended", wxCheckBox)->SetValue(opt.outputHDRBlended);
00445     XRCCTRL(*this, "pano_cb_hdr_output_blended", wxCheckBox)->Show(opt.outputHDRBlended || m_guiLevel>GUI_SIMPLE);
00446 
00447     //remapped images
00448     XRCCTRL(*this, "pano_text_remapped_images", wxStaticText)->Show(opt.outputLDRLayers || opt.outputLDRExposureRemapped || opt.outputHDRLayers || m_guiLevel>GUI_SIMPLE);
00449     XRCCTRL(*this, "pano_cb_ldr_output_layers", wxCheckBox)->SetValue(opt.outputLDRLayers);
00450     XRCCTRL(*this, "pano_cb_ldr_output_layers", wxCheckBox)->Show(opt.outputLDRLayers || m_guiLevel>GUI_SIMPLE);
00451     XRCCTRL(*this, "pano_cb_ldr_output_exposure_remapped", wxCheckBox)->SetValue(opt.outputLDRExposureRemapped);
00452     XRCCTRL(*this, "pano_cb_ldr_output_exposure_remapped", wxCheckBox)->Show(opt.outputLDRExposureRemapped || m_guiLevel>GUI_SIMPLE);
00453     XRCCTRL(*this, "pano_cb_hdr_output_layers", wxCheckBox)->SetValue(opt.outputHDRLayers);
00454     XRCCTRL(*this, "pano_cb_hdr_output_layers", wxCheckBox)->Show(opt.outputHDRLayers || m_guiLevel>GUI_SIMPLE);
00455 
00456     //stacks
00457     XRCCTRL(*this, "pano_text_stacks", wxStaticText)->Show(opt.outputHDRStacks || opt.outputLDRStacks || m_guiLevel>GUI_SIMPLE);
00458     XRCCTRL(*this, "pano_cb_ldr_output_stacks", wxCheckBox)->SetValue(opt.outputLDRStacks);
00459     XRCCTRL(*this, "pano_cb_ldr_output_stacks", wxCheckBox)->Show(opt.outputLDRStacks || m_guiLevel>GUI_SIMPLE);
00460     XRCCTRL(*this, "pano_cb_hdr_output_stacks", wxCheckBox)->SetValue(opt.outputHDRStacks);
00461     XRCCTRL(*this, "pano_cb_hdr_output_stacks", wxCheckBox)->Show(opt.outputHDRStacks || m_guiLevel>GUI_SIMPLE);
00462 
00463     //layers
00464     XRCCTRL(*this, "pano_text_layers", wxStaticText)->Show(opt.outputLDRExposureLayers || m_guiLevel>GUI_SIMPLE);
00465     XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers", wxCheckBox)->SetValue(opt.outputLDRExposureLayers);
00466     XRCCTRL(*this, "pano_cb_ldr_output_exposure_layers", wxCheckBox)->Show(opt.outputLDRExposureLayers || m_guiLevel>GUI_SIMPLE);
00467 
00468     bool anyOutputSelected = (opt.outputLDRBlended || 
00469                               opt.outputLDRLayers || 
00470                               opt.outputLDRExposureLayers || 
00471                               opt.outputLDRExposureBlended || 
00472                               opt.outputLDRExposureLayersFused || 
00473                               opt.outputLDRExposureRemapped || 
00474                               opt.outputLDRStacks ||
00475                               opt.outputHDRBlended || 
00476                               opt.outputHDRStacks || 
00477                               opt.outputHDRLayers);
00478     
00479     //do not let the user stitch unless there are active images and an output selected.
00480     bool any_output_possible = hasImages && anyOutputSelected;
00481     m_StitchButton->Enable(any_output_possible);
00482 
00483 #ifdef STACK_CHECK //Disabled for 0.7.0 release
00484     if (hasStacks) {
00485         XRCCTRL(*this,"pano_cb_ldr_output_blended",wxCheckBox)->Disable();
00486         XRCCTRL(*this,"pano_cb_ldr_output_layers",wxCheckBox)->Disable();
00487 
00488         XRCCTRL(*this,"pano_cb_ldr_output_exposure_layers",wxCheckBox)->Enable();
00489         XRCCTRL(*this,"pano_cb_ldr_output_exposure_blended",wxCheckBox)->Enable();
00490         XRCCTRL(*this,"pano_cb_ldr_output_exposure_remapped",wxCheckBox)->Enable();
00491         XRCCTRL(*this,"pano_cb_hdr_output_blended",wxCheckBox)->Enable();
00492         XRCCTRL(*this,"pano_cb_hdr_output_stacks",wxCheckBox)->Enable();
00493         XRCCTRL(*this,"pano_cb_hdr_output_layers",wxCheckBox)->Enable();
00494 
00495     } else {
00496         XRCCTRL(*this,"pano_cb_ldr_output_blended",wxCheckBox)->Enable();
00497         XRCCTRL(*this,"pano_cb_ldr_output_layers",wxCheckBox)->Enable();
00498 
00499         XRCCTRL(*this,"pano_cb_ldr_output_exposure_layers",wxCheckBox)->Disable();
00500         XRCCTRL(*this,"pano_cb_ldr_output_exposure_blended",wxCheckBox)->Disable();
00501         XRCCTRL(*this,"pano_cb_ldr_output_exposure_remapped",wxCheckBox)->Disable();
00502 
00503         XRCCTRL(*this,"pano_cb_hdr_output_blended",wxCheckBox)->Disable();
00504         XRCCTRL(*this,"pano_cb_hdr_output_stacks",wxCheckBox)->Disable();
00505         XRCCTRL(*this,"pano_cb_hdr_output_layers",wxCheckBox)->Disable();
00506     }
00507 #endif
00508 
00509     m_RemapperChoice->Show(m_guiLevel>GUI_SIMPLE);
00510     m_RemapperChoice->Enable(m_guiLevel>GUI_SIMPLE);
00511     XRCCTRL(*this, "pano_button_remapper_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
00512     XRCCTRL(*this, "pano_button_remapper_opts", wxButton)->Enable(m_guiLevel>GUI_SIMPLE);
00513     XRCCTRL(*this, "pano_text_remapper", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
00514     XRCCTRL(*this, "pano_text_processing", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
00515 
00516     bool blenderEnabled = (opt.outputLDRBlended || 
00517                           opt.outputLDRExposureBlended || 
00518                           opt.outputLDRExposureLayersFused || 
00519                           opt.outputLDRExposureLayers || 
00520                           opt.outputHDRBlended ) && m_guiLevel>GUI_SIMPLE;
00521 
00522     m_BlenderChoice->Enable(blenderEnabled);
00523     m_BlenderChoice->Show(m_guiLevel>GUI_SIMPLE);
00524     // select correct blending mechanism
00525     SelectListValue(m_BlenderChoice, opt.blendMode);
00526     XRCCTRL(*this, "pano_button_blender_opts", wxButton)->Enable(blenderEnabled);
00527     XRCCTRL(*this, "pano_button_blender_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
00528     XRCCTRL(*this, "pano_text_blender", wxStaticText)->Enable(blenderEnabled);
00529     XRCCTRL(*this, "pano_text_blender", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
00530 
00531     bool fusionEnabled = (opt.outputLDRExposureBlended || opt.outputLDRExposureLayersFused || opt.outputLDRStacks) && m_guiLevel>GUI_SIMPLE;
00532     m_FusionChoice->Enable(fusionEnabled);
00533     m_FusionChoice->Show(m_guiLevel>GUI_SIMPLE);
00534     XRCCTRL(*this, "pano_button_fusion_opts", wxButton)->Enable(fusionEnabled);
00535     XRCCTRL(*this, "pano_button_fusion_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
00536     XRCCTRL(*this, "pano_text_fusion", wxStaticText)->Enable(fusionEnabled);
00537     XRCCTRL(*this, "pano_text_fusion", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
00538 
00539     bool hdrMergeEnabled = (opt.outputHDRBlended || opt.outputHDRStacks) && m_guiLevel>GUI_SIMPLE;
00540     m_HDRMergeChoice->Enable(hdrMergeEnabled);
00541     m_HDRMergeChoice->Show(m_guiLevel>GUI_SIMPLE);
00542     XRCCTRL(*this, "pano_button_hdrmerge_opts", wxButton)->Enable(hdrMergeEnabled);
00543     XRCCTRL(*this, "pano_button_hdrmerge_opts", wxButton)->Show(m_guiLevel>GUI_SIMPLE);
00544     XRCCTRL(*this, "pano_text_hdrmerge", wxStaticText)->Enable(hdrMergeEnabled);
00545     XRCCTRL(*this, "pano_text_hdrmerge", wxStaticText)->Show(m_guiLevel>GUI_SIMPLE);
00546 
00547     // output file mode
00548     bool ldr_pano_enabled = opt.outputLDRBlended ||
00549                             opt.outputLDRExposureBlended ||
00550                             opt.outputLDRExposureLayersFused;
00551     
00552     XRCCTRL(*this, "pano_output_ldr_format_label", wxStaticText)->Enable(ldr_pano_enabled);
00553     m_FileFormatOptionsLabel->Enable(ldr_pano_enabled);
00554     m_FileFormatChoice->Enable(ldr_pano_enabled);
00555     m_FileFormatJPEGQualityText->Enable(ldr_pano_enabled);
00556     m_FileFormatTIFFCompChoice->Enable(ldr_pano_enabled);
00557     
00558     long i=0;
00559     if (opt.outputImageType == "tif") {
00560         i = 0;
00561         m_FileFormatOptionsLabel->Show();
00562         m_FileFormatOptionsLabel->SetLabel(_("Compression:"));
00563         m_FileFormatJPEGQualityText->Hide();
00564         m_FileFormatTIFFCompChoice->Show();
00565         if (opt.outputImageTypeCompression  == "PACKBITS") {
00566             m_FileFormatTIFFCompChoice->SetSelection(1);
00567         } else if (opt.outputImageTypeCompression == "LZW") {
00568             m_FileFormatTIFFCompChoice->SetSelection(2);
00569         } else if (opt.outputImageTypeCompression  == "DEFLATE") {
00570             m_FileFormatTIFFCompChoice->SetSelection(3);
00571         } else {
00572             m_FileFormatTIFFCompChoice->SetSelection(0);
00573         }
00574     } else if (opt.outputImageType == "jpg") {
00575         i = 1;
00576         m_FileFormatOptionsLabel->Show();
00577         m_FileFormatOptionsLabel->SetLabel(_("Quality:"));
00578         m_FileFormatJPEGQualityText->Show();
00579         m_FileFormatTIFFCompChoice->Hide();
00580         m_FileFormatJPEGQualityText->ChangeValue(wxString::Format(wxT("%d"), opt.quality));
00581     } else if (opt.outputImageType == "png") {
00582         m_FileFormatOptionsLabel->Hide();
00583         m_FileFormatJPEGQualityText->Hide();
00584         m_FileFormatTIFFCompChoice->Hide();
00585         i = 2;
00586     } else if (opt.outputImageType == "exr") {
00588         m_FileFormatOptionsLabel->Hide();
00589         m_FileFormatJPEGQualityText->Hide();
00590         m_FileFormatTIFFCompChoice->Hide();
00591         i = 3;
00592     } else
00593         wxLogError(wxT("INTERNAL error: unknown output image type"));
00594 
00595     m_FileFormatChoice->SetSelection(i);
00596 
00597     bool hdr_pano_enabled = opt.outputHDRBlended;
00598     
00599     XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Enable(hdr_pano_enabled);
00600     XRCCTRL(*this, "pano_output_hdr_format_label", wxStaticText)->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
00601     m_HDRFileFormatChoice->Enable(hdr_pano_enabled);
00602     m_HDRFileFormatChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
00603     m_HDRFileFormatLabelTIFFCompression->Enable(hdr_pano_enabled);
00604     m_HDRFileFormatLabelTIFFCompression->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
00605     m_FileFormatHDRTIFFCompChoice->Enable(hdr_pano_enabled);
00606     m_FileFormatHDRTIFFCompChoice->Show(hdr_pano_enabled || m_guiLevel>GUI_SIMPLE);
00607     
00608     i=0;
00609     if (opt.outputImageTypeHDR == "exr") {
00610         i = 0;
00611         m_HDRFileFormatLabelTIFFCompression->Hide();
00612         m_FileFormatHDRTIFFCompChoice->Hide();
00613     } else if (opt.outputImageTypeHDR == "tif") {
00614         i = 1;
00615         m_HDRFileFormatLabelTIFFCompression->Show();
00616         m_FileFormatHDRTIFFCompChoice->Show();
00617         if (opt.outputImageTypeHDRCompression  == "PACKBITS") {
00618             m_FileFormatHDRTIFFCompChoice->SetSelection(1);
00619         } else if (opt.outputImageTypeHDRCompression == "LZW") {
00620             m_FileFormatHDRTIFFCompChoice->SetSelection(2);
00621         } else if (opt.outputImageTypeHDRCompression  == "DEFLATE") {
00622             m_FileFormatHDRTIFFCompChoice->SetSelection(3);
00623         } else {
00624             m_FileFormatHDRTIFFCompChoice->SetSelection(0);
00625         }
00626     } else
00627         wxLogError(wxT("INTERNAL error: unknown hdr output image type"));
00628 
00629     m_HDRFileFormatChoice->SetSelection(i);
00630 
00631     m_pano_ctrls->FitInside();
00632     Layout();
00633     Thaw();
00634 
00635 #ifdef __WXMSW__
00636     this->Refresh(false);
00637 #endif
00638 }
00639 
00640 void PanoPanel::ProjectionChanged ( wxCommandEvent & e )
00641 {
00642     if (updatesDisabled) return;
00643     HuginBase::PanoramaOptions opt = pano->getOptions();
00644 //    PanoramaOptions::ProjectionFormat oldP = opt.getProjection();
00645 
00646     HuginBase::PanoramaOptions::ProjectionFormat newP = (HuginBase::PanoramaOptions::ProjectionFormat) m_ProjectionChoice->GetSelection();
00647 //    int w = opt.getWidth();
00648 //    int h = opt.getHeight();
00649     opt.setProjection(newP);
00650 
00651     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00652         new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00653         );
00654     DEBUG_DEBUG ("Projection changed: "  << newP)
00655 }
00656 
00657 void PanoPanel::HFOVChanged ( wxCommandEvent & e )
00658 {
00659     if (updatesDisabled) return;
00660     HuginBase::PanoramaOptions opt = pano->getOptions();
00661 
00662 
00663     wxString text = m_HFOVText->GetValue();
00664     DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
00665     if (text == wxT("")) {
00666         return;
00667     }
00668 
00669     double hfov;
00670     if (!hugin_utils::str2double(text, hfov)) {
00671         wxLogError(_("Value must be numeric."));
00672         return;
00673     }
00674 
00675     if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
00676         wxLogError(wxString::Format(
00677             _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
00678             opt.getMaxHFOV()));
00679     }
00680     opt.setHFOV(hfov);
00681     // recalculate panorama height...
00682     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00683         new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00684         );
00685 
00686     DEBUG_INFO ( "new hfov: " << hfov )
00687 }
00688 
00689 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
00690 {
00691     if (updatesDisabled) return;
00692     HuginBase::PanoramaOptions opt = pano->getOptions();
00693 
00694     wxString text = m_VFOVText->GetValue();
00695     DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
00696     if (text == wxT("")) {
00697         return;
00698     }
00699 
00700     double vfov;
00701     if (!hugin_utils::str2double(text, vfov)) {
00702         wxLogError(_("Value must be numeric."));
00703         return;
00704     }
00705 
00706     if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
00707         wxLogError(wxString::Format(
00708             _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
00709             opt.getMaxVFOV()));
00710         vfov = opt.getMaxVFOV();
00711     }
00712     opt.setVFOV(vfov);
00713     // recalculate panorama height...
00714     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00715         new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00716         );
00717 
00718     DEBUG_INFO ( "new vfov: " << vfov )
00719 }
00720 
00721 /*
00722 void PanoPanel::VFOVChanged ( wxCommandEvent & e )
00723 {
00724     DEBUG_TRACE("")
00725     if (updatesDisabled) return;
00726     PanoramaOptions opt = pano->getOptions();
00727     int vfov = m_VFOVSpin->GetValue() ;
00728 
00729     if (vfov != opt.getVFOV()) {
00730         opt.setVFOV(vfov);
00731         GlobalCmdHist::getInstance().addCommand(
00732             new PanoCommand::SetPanoOptionsCmd( pano, opt )
00733             );
00734         DEBUG_INFO ( "new vfov: " << vfov << " => height: " << opt.getHeight() );
00735     } else {
00736         DEBUG_DEBUG("not setting same fov");
00737     }
00738 }
00739 */
00740 
00741 void PanoPanel::WidthChanged ( wxCommandEvent & e )
00742 {
00743     if (updatesDisabled) return;
00744     HuginBase::PanoramaOptions opt = pano->getOptions();
00745     long nWidth;
00746     if (m_WidthTxt->GetValue().ToLong(&nWidth)) {
00747         if (nWidth <= 0) return;
00748         opt.setWidth((unsigned int) nWidth, m_keepViewOnResize);
00749         PanoCommand::GlobalCmdHist::getInstance().addCommand(
00750             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00751             );
00752         DEBUG_INFO(nWidth );
00753     } else {
00754         wxLogError(_("width needs to be an integer bigger than 0"));
00755     }
00756 }
00757 
00758 void PanoPanel::HeightChanged ( wxCommandEvent & e )
00759 {
00760     if (updatesDisabled) return;
00761     HuginBase::PanoramaOptions opt = pano->getOptions();
00762     long nHeight;
00763     if (m_HeightTxt->GetValue().ToLong(&nHeight)) {
00764         if(nHeight <= 0) return;
00765         opt.setHeight((unsigned int) nHeight);
00766         PanoCommand::GlobalCmdHist::getInstance().addCommand(
00767                 new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00768                                                );
00769         DEBUG_INFO(nHeight);
00770     } else {
00771         wxLogError(_("height needs to be an integer bigger than 0"));
00772     }
00773 }
00774 
00775 void PanoPanel::ROIChanged ( wxCommandEvent & e )
00776 {
00777     if (updatesDisabled) return;
00778     HuginBase::PanoramaOptions opt = pano->getOptions();
00779     long left, right, top, bottom;
00780     if (!m_ROITopTxt->GetValue().ToLong(&top)) {
00781         wxLogError(_("Top needs to be an integer bigger than 0"));
00782         return;
00783     }
00784     if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
00785         wxLogError(_("left needs to be an integer bigger than 0"));
00786         return;
00787     }
00788     if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
00789         wxLogError(_("right needs to be an integer bigger than 0"));
00790         return;
00791     }
00792     if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
00793         wxLogError(_("bottom needs to be an integer bigger than 0"));
00794         return;
00795     }
00796     opt.setROI(vigra::Rect2D(left, top, right, bottom));
00797 
00798     // make sure that left is really to the left of right
00799     if(opt.getROI().width()<1) {
00800         wxLogError(_("Left boundary must be smaller than right."));
00801         UpdateDisplay(pano->getOptions(), false);
00802         return;
00803     }
00804     // make sure that top is really higher than bottom
00805     if(opt.getROI().height()<1) {
00806         wxLogError(_("Top boundary must be smaller than bottom."));
00807         UpdateDisplay(pano->getOptions(), false);
00808         return;
00809     }
00810 
00811     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00812             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00813                                            );
00814 }
00815 
00816 
00817 void PanoPanel::EnableControls(bool enable)
00818 {
00819 //    m_HFOVSpin->Enable(enable);
00820 //    m_VFOVSpin->Enable(enable);
00821     m_WidthTxt->Enable(enable);
00822     m_RemapperChoice->Enable(enable);
00823     m_BlenderChoice->Enable(enable);
00824 //    m_CalcHFOVButton->Enable(enable);
00825 //    m_CalcOptWidthButton->Enable(enable);
00826 //    m_CalcOptROIButton->Enable(enable);
00827 }
00828 
00829 void PanoPanel::RemapperChanged(wxCommandEvent & e)
00830 {
00831     int remapper = m_RemapperChoice->GetSelection();
00832     DEBUG_DEBUG("changing remapper to " << remapper);
00833 
00834     HuginBase::PanoramaOptions opt = pano->getOptions();
00835     if (remapper == 1) {
00836         opt.remapper = HuginBase::PanoramaOptions::PTMENDER;
00837     } else {
00838         opt.remapper = HuginBase::PanoramaOptions::NONA;
00839     }
00840 
00841     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00842             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00843             );
00844 }
00845 
00846 void PanoPanel::OnRemapperOptions(wxCommandEvent & e)
00847 {
00848     HuginBase::PanoramaOptions opt = pano->getOptions();
00849     if (opt.remapper == HuginBase::PanoramaOptions::NONA) {
00850         wxDialog dlg;
00851         wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("nona_options_dialog"));
00852         wxChoice * interpol_choice = XRCCTRL(dlg, "nona_choice_interpolator", wxChoice);
00853         wxCheckBox * cropped_cb = XRCCTRL(dlg, "nona_save_cropped", wxCheckBox);
00854         interpol_choice->SetSelection(opt.interpolator);
00855         cropped_cb->SetValue(opt.tiff_saveROI);
00856         dlg.CentreOnParent();
00857 
00858         if (dlg.ShowModal() == wxID_OK) {
00859             int interpol = interpol_choice->GetSelection();
00860             if (interpol >= 0) {
00861                 opt.interpolator = (vigra_ext::Interpolator) interpol;
00862             }
00863             opt.tiff_saveROI = cropped_cb->GetValue();
00864             PanoCommand::GlobalCmdHist::getInstance().addCommand(
00865                 new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00866                 );
00867         }
00868     } else {
00869         wxLogError(_(" PTmender options not yet implemented"));
00870     }
00871 }
00872 
00873 void PanoPanel::BlenderChanged(wxCommandEvent & e)
00874 {
00875     HuginBase::PanoramaOptions opt = pano->getOptions();
00876     opt.blendMode = static_cast<HuginBase::PanoramaOptions::BlendingMechanism>(GetSelectedValue(m_BlenderChoice));
00877 
00878     PanoCommand::GlobalCmdHist::getInstance().addCommand(
00879             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00880             );
00881 }
00882 
00883 void PanoPanel::OnBlenderOptions(wxCommandEvent & e)
00884 {
00885     HuginBase::PanoramaOptions opt = pano->getOptions();
00886     if (opt.blendMode == HuginBase::PanoramaOptions::ENBLEND_BLEND) {
00887         wxDialog dlg;
00888         wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("enblend_options_dialog"));
00889         wxTextCtrl * enblend_opts_text = XRCCTRL(dlg, "blender_arguments_text", wxTextCtrl);
00890         enblend_opts_text->ChangeValue(wxString(opt.enblendOptions.c_str(), wxConvLocal));
00891         dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp(wxT("Enblend.html")); }, wxID_HELP);
00892         dlg.CentreOnParent();
00893 
00894         if (dlg.ShowModal() == wxID_OK) {
00895             if (enblend_opts_text->GetValue().length() > 0) {
00896                 opt.enblendOptions = enblend_opts_text->GetValue().mb_str(wxConvLocal);
00897             }
00898             else
00899             {
00900                 opt.enblendOptions = wxConfigBase::Get()->Read(wxT("Enblend/Args"),wxT(HUGIN_ENBLEND_ARGS)).mb_str(wxConvLocal);
00901             };
00902             PanoCommand::GlobalCmdHist::getInstance().addCommand(
00903                 new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00904                 );
00905         }
00906     } 
00907     else
00908     {
00909         if (opt.blendMode == HuginBase::PanoramaOptions::INTERNAL_BLEND)
00910         {
00911             wxDialog dlg;
00912             wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("verdandi_options_dialog"));
00913             wxChoice * verdandiBlendModeChoice = XRCCTRL(dlg, "verdandi_blend_mode_choice", wxChoice);
00914             if (opt.verdandiOptions.find("--seam=blend")!=std::string::npos)
00915             {
00916                 verdandiBlendModeChoice->SetSelection(1);
00917             }
00918             else
00919             {
00920                 verdandiBlendModeChoice->SetSelection(0);
00921             };
00922             dlg.CentreOnParent();
00923 
00924             if (dlg.ShowModal() == wxID_OK)
00925             {
00926                 if (verdandiBlendModeChoice->GetSelection() == 1)
00927                 {
00928                     opt.verdandiOptions = "--seam=blend";
00929                 }
00930                 else
00931                 {
00932                     opt.verdandiOptions = "";
00933                 };
00934                 PanoCommand::GlobalCmdHist::getInstance().addCommand(new PanoCommand::SetPanoOptionsCmd(*pano, opt));
00935             };
00936         }
00937         else
00938         {
00939             wxLogError(_(" PTblender options not yet implemented"));
00940         };
00941     };
00942 }
00943 
00944 void PanoPanel::FusionChanged(wxCommandEvent & e)
00945 {
00946     int fusion = m_FusionChoice->GetSelection();
00947     DEBUG_DEBUG("changing stacking program to " << fusion);
00948 }
00949 
00950 void PanoPanel::OnFusionOptions(wxCommandEvent & e)
00951 {
00952     HuginBase::PanoramaOptions opt = pano->getOptions();
00953     wxDialog dlg;
00954     wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("enfuse_options_dialog"));
00955     wxTextCtrl * enfuse_opts_text = XRCCTRL(dlg, "enfuse_arguments_text", wxTextCtrl);
00956     enfuse_opts_text->ChangeValue(wxString(opt.enfuseOptions.c_str(), wxConvLocal));
00957     dlg.Bind(wxEVT_COMMAND_BUTTON_CLICKED, [](wxCommandEvent &) {MainFrame::Get()->DisplayHelp(wxT("Enfuse.html")); }, wxID_HELP);
00958     dlg.CentreOnParent();
00959 
00960     if (dlg.ShowModal() == wxID_OK) {
00961         if (enfuse_opts_text->GetValue().length() > 0) {
00962             opt.enfuseOptions = enfuse_opts_text->GetValue().mb_str(wxConvLocal);
00963         }
00964         else
00965         {
00966             opt.enfuseOptions = wxConfigBase::Get()->Read(wxT("Enfuse/Args"),wxT(HUGIN_ENFUSE_ARGS)).mb_str(wxConvLocal);
00967         };
00968         PanoCommand::GlobalCmdHist::getInstance().addCommand(
00969             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00970             );
00971     }
00972 }
00973 
00974 
00975 void PanoPanel::HDRMergeChanged(wxCommandEvent & e)
00976 {
00977     int blender = m_HDRMergeChoice->GetSelection();
00978     DEBUG_DEBUG("changing HDR merger to " << blender);
00979 }
00980 
00981 void PanoPanel::OnHDRMergeOptions(wxCommandEvent & e)
00982 {
00983     HuginBase::PanoramaOptions opt = pano->getOptions();
00984     if (opt.hdrMergeMode == HuginBase::PanoramaOptions::HDRMERGE_AVERAGE) {
00985         HDRMergeOptionsDialog dlg(this);
00986         dlg.SetCommandLineArgument(wxString(opt.hdrmergeOptions.c_str(), wxConvLocal));
00987         if (dlg.ShowModal() == wxOK) 
00988         {
00989             opt.hdrmergeOptions=dlg.GetCommandLineArgument().mb_str(wxConvLocal);
00990             PanoCommand::GlobalCmdHist::getInstance().addCommand(
00991                 new PanoCommand::SetPanoOptionsCmd( *pano, opt )
00992                 );
00993         }
00994     } else {
00995         wxLogError(_(" Options for this HDRMerge program not yet implemented"));
00996     }
00997 }
00998 
00999 
01000 
01001 void PanoPanel::DoCalcFOV(wxCommandEvent & e)
01002 {
01003     DEBUG_TRACE("");
01004     if (pano->getActiveImages().size() == 0) return;
01005 
01006     HuginBase::PanoramaOptions opt = pano->getOptions();
01007     HuginBase::CalculateFitPanorama fitPano(*pano);
01008     fitPano.run();
01009     opt.setHFOV(fitPano.getResultHorizontalFOV());
01010     opt.setHeight(hugin_utils::roundi(fitPano.getResultHeight()));
01011 
01012     DEBUG_INFO ( "hfov: " << opt.getHFOV() << "  w: " << opt.getWidth() << " h: " << opt.getHeight() << "  => vfov: " << opt.getVFOV()  << "  before update");
01013 
01014     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01015         new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01016         );
01017 
01018     HuginBase::PanoramaOptions opt2 = pano->getOptions();
01019     DEBUG_INFO ( "hfov: " << opt2.getHFOV() << "  w: " << opt2.getWidth() << " h: " << opt2.getHeight() << "  => vfov: " << opt2.getVFOV()  << "  after update");
01020 
01021 }
01022 
01023 void PanoPanel::DoCalcOptimalWidth(wxCommandEvent & e)
01024 {
01025     if (pano->getActiveImages().size() == 0) return;
01026 
01027     HuginBase::PanoramaOptions opt = pano->getOptions();
01028     double sizeFactor = 1.0;
01029     if (wxGetKeyState(WXK_COMMAND))
01030     {
01031         wxConfigBase::Get()->Read(wxT("/Assistant/panoDownsizeFactor"), &sizeFactor, HUGIN_ASS_PANO_DOWNSIZE_FACTOR);
01032     };
01033 
01034     unsigned width = hugin_utils::roundi(HuginBase::CalculateOptimalScale::calcOptimalScale(*pano) * opt.getWidth() * sizeFactor);
01035 
01036     if (width > 0) {
01037         opt.setWidth( width );
01038         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01039             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01040             );
01041     }
01042     DEBUG_INFO ( "new optimal width: " << opt.getWidth() );
01043 }
01044 
01045 
01046 void PanoPanel::DoCalcOptimalROI(wxCommandEvent & e)
01047 {
01048     DEBUG_INFO("Dirty ROI Calc\n");
01049     if (pano->getActiveImages().size() == 0)
01050     {
01051         return;
01052     };
01053 
01054     vigra::Rect2D newROI;
01055     {
01056         ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
01057         HuginBase::CalculateOptimalROI cropPano(*pano, &progress);
01058         cropPano.run();
01059         if (cropPano.hasRunSuccessfully())
01060         {
01061             newROI = cropPano.getResultOptimalROI();
01062         };
01063     };
01064 
01065     //set the ROI - fail if the right/bottom is zero, meaning all zero
01066     if(!newROI.isEmpty())
01067     {
01068         HuginBase::PanoramaOptions opt = pano->getOptions();
01069         opt.setROI(newROI);
01070         PanoCommand::GlobalCmdHist::getInstance().addCommand(
01071             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01072             );
01073     };
01074 };
01075 
01076 void PanoPanel::DoStitch()
01077 {
01078     if (pano->getNrOfImages() == 0) {
01079         return;
01080     }
01081     
01082     if (!CheckGoodSize()) {
01083         // oversized pano and the user no longer wants to stitch.
01084         return;
01085     }
01086     if (!CheckHasImages())
01087     {
01088         // output ROI contains no images
01089         return;
01090     };
01091 
01092     // save project
01093     // copy pto file to temporary file
01094     wxString tempDir= wxConfigBase::Get()->Read(wxT("tempDir"),wxT(""));
01095     if(!tempDir.IsEmpty())
01096         if(tempDir.Last()!=wxFileName::GetPathSeparator())
01097             tempDir.Append(wxFileName::GetPathSeparator());
01098     wxString currentPTOfn = wxFileName::CreateTempFileName(tempDir+wxT("huginpto_"));
01099     if(currentPTOfn.size() == 0) {
01100         wxMessageBox(_("Could not create temporary project file"),_("Error"),
01101                 wxCANCEL | wxICON_ERROR,this);
01102         return;
01103     }
01104     DEBUG_DEBUG("tmp PTO file: " << (const char *)currentPTOfn.mb_str(wxConvLocal));
01105     // copy is not enough, need to adjust image path names...
01106     std::ofstream script(currentPTOfn.mb_str(HUGIN_CONV_FILENAME));
01107     HuginBase::UIntSet all;
01108     if (pano->getNrOfImages() > 0) {
01109         fill_set(all, 0, pano->getNrOfImages()-1);
01110     }
01111     pano->printPanoramaScript(script, pano->getOptimizeVector(), pano->getOptions(), all, false, "");
01112     script.close();
01113 
01114 //    wxCommandEvent dummy;
01115 //    MainFrame::Get()->OnSaveProject(dummy);
01116 
01117 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01118     // HuginStitchProject inside main bundle
01119     wxString hugin_stitch_project = MacGetPathToBundledAppMainExecutableFile(CFSTR("HuginStitchProject.app"));
01120     if(hugin_stitch_project == wxT(""))
01121     {
01122         DEBUG_ERROR("hugin_stitch_project could not be found in the bundle.");
01123         return;
01124     }
01125     hugin_stitch_project = hugin_utils::wxQuoteFilename(hugin_stitch_project);
01126 #elif defined __WXMAC__
01127     // HuginStitchProject installed in INSTALL_OSX_BUNDLE_DIR
01128     wxFileName hugin_stitch_project_app(wxT(INSTALL_OSX_BUNDLE_DIR), wxEmptyString);
01129     hugin_stitch_project_app.AppendDir(wxT("HuginStitchProject.app"));
01130     CFStringRef stitchProjectAppPath = MacCreateCFStringWithWxString(hugin_stitch_project_app.GetFullPath());
01131     wxString hugin_stitch_project = MacGetPathToMainExecutableFileOfBundle(stitchProjectAppPath);
01132     CFRelease(stitchProjectAppPath);
01133 #else
01134     wxString hugin_stitch_project = wxT("hugin_stitch_project");
01135 #endif
01136 
01137     // Derive a default output prefix from the project filename if set, otherwise default project filename
01138     wxFileName outputPrefix(getDefaultOutputName(MainFrame::Get()->getProjectName(), *pano));
01139     outputPrefix.Normalize();
01140 
01141     // Show a file save dialog so user can confirm/change the prefix.
01142     // (We don't have to worry about overwriting existing files, since hugin_switch_project checks this.)
01143     // TODO: The following code is similar to stitchApp::OnInit in hugin_switch_project.cpp. Should be refactored.
01144     // TODO: We should save the output prefix somewhere, so we can recall it as the default if the user stitches this project again.
01145     wxFileDialog dlg(this,_("Specify output prefix"),
01146                      outputPrefix.GetPath(), outputPrefix.GetName(), wxT(""),
01147                      wxFD_SAVE, wxDefaultPosition);
01148     if (dlg.ShowModal() != wxID_OK)
01149     {
01150         return;
01151     };
01152     while(containsInvalidCharacters(dlg.GetPath()))
01153     {
01154         wxArrayString list;
01155         list.Add(dlg.GetPath());
01156         ShowFilenameWarning(this, list);
01157         if(dlg.ShowModal()!=wxID_OK)
01158             return;
01159     };
01160     wxFileName prefix(dlg.GetPath());
01161     while (!prefix.IsDirWritable())
01162     {
01163         wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
01164 #ifdef __WXMSW__
01165             wxT("Hugin"),
01166 #else
01167             wxT(""),
01168 #endif
01169             wxOK | wxICON_INFORMATION);
01170         if (dlg.ShowModal() != wxID_OK)
01171         {
01172             return;
01173         };
01174         prefix = dlg.GetPath();
01175     };
01176     // check free space
01177     if (!CheckFreeSpace(prefix.GetPath()))
01178     {
01179         return;
01180     };
01181 
01182     wxString switches(wxT(" --delete -o "));
01183     if(wxConfigBase::Get()->Read(wxT("/Processor/overwrite"), HUGIN_PROCESSOR_OVERWRITE) == 1)
01184         switches=wxT(" --overwrite")+switches;
01185     wxString command = hugin_stitch_project + switches + hugin_utils::wxQuoteFilename(dlg.GetPath()) + wxT(" ") + hugin_utils::wxQuoteFilename(currentPTOfn);
01186     
01187     wxConfigBase::Get()->Flush();
01188 #ifdef __WXGTK__
01189     // work around a wxExecute bug/problem
01190     // (endless polling of fd 0 and 1 in hugin_stitch_project)
01191     wxProcess *my_process = new wxProcess(this);
01192     my_process->Redirect();
01193 
01194     // Delete itself once processes terminated.
01195     my_process->Detach();
01196     wxExecute(command,wxEXEC_ASYNC, my_process);
01197 #else
01198     wxExecute(command);
01199 #endif
01200     HuginBase::LensDB::SaveLensDataFromPano(*pano);
01201 }
01202 
01203 void PanoPanel::DoSendToBatch()
01204 {
01205     if (pano->getNrOfImages() == 0)
01206     {
01207         return;
01208     }
01209     
01210     if (!CheckGoodSize())
01211     {
01212         // oversized pano and the user no longer wants to stitch.
01213         return;
01214     }
01215     if( !CheckHasImages())
01216     {
01217         // output ROI contains no images
01218         return;
01219     };
01220 
01221     wxString switches(wxT(" "));
01222     if (wxConfigBase::Get()->Read(wxT("/Processor/start"), HUGIN_PROCESSOR_START) != 0)
01223     {
01224         switches += wxT("-b ");
01225     }
01226     if (wxConfigBase::Get()->Read(wxT("/Processor/overwrite"), HUGIN_PROCESSOR_OVERWRITE) != 0)
01227     {
01228         switches += wxT("-o ");
01229     }
01230     if (wxConfigBase::Get()->Read(wxT("/Processor/verbose"), HUGIN_PROCESSOR_VERBOSE) != 0)
01231     {
01232         switches += wxT("-v ");
01233     }
01234     if(pano->isDirty())
01235     {
01236         bool showDlg=wxConfigBase::Get()->Read(wxT("ShowSaveMessage"), 1l)==1;
01237         if(showDlg)
01238         {
01239             wxDialog dlg;
01240             wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("stitch_message_dlg"));
01241             if(dlg.ShowModal())
01242             {
01243                 if(XRCCTRL(dlg, "stitch_dont_show_checkbox", wxCheckBox)->IsChecked())
01244                 {
01245                     wxConfigBase::Get()->Write(wxT("ShowSaveMessage"), 0l);
01246                 };
01247             };
01248         };
01249         wxCommandEvent dummy;
01250         MainFrame::Get()->OnSaveProject(dummy);
01251         //test if save was sucessful
01252         if(pano->isDirty())
01253         {
01254             return;
01255         };
01256     };
01257     wxString projectFile = MainFrame::Get()->getProjectName();
01258     if(wxFileName::FileExists(projectFile))
01259     {
01260         wxFileName outputPrefix(getDefaultOutputName(projectFile, *pano));
01261         outputPrefix.Normalize();
01262 
01263         // Show a file save dialog so user can confirm/change the prefix.
01264         // (We don't have to worry about overwriting existing files, since PTBatcherGUI checks this, or the overwrite flag was set.)
01265         wxFileDialog dlg(this,_("Specify output prefix"),
01266                          outputPrefix.GetPath(), outputPrefix.GetName(), wxT(""),
01267                          wxFD_SAVE, wxDefaultPosition);
01268         if (dlg.ShowModal() != wxID_OK)
01269         {
01270             return;
01271         };
01272         while(containsInvalidCharacters(dlg.GetPath()))
01273         {
01274             wxArrayString list;
01275             list.Add(dlg.GetPath());
01276             ShowFilenameWarning(this, list);
01277             if(dlg.ShowModal()!=wxID_OK)
01278                 return;
01279         };
01280         wxFileName prefix(dlg.GetPath());
01281         while (!prefix.IsDirWritable())
01282         {
01283             wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
01284 #ifdef __WXMSW__
01285                 wxT("Hugin"),
01286 #else
01287                 wxT(""),
01288 #endif
01289                 wxOK | wxICON_INFORMATION);
01290             if (dlg.ShowModal() != wxID_OK)
01291             {
01292                 return;
01293             };
01294             prefix = dlg.GetPath();
01295         };
01296         // check free space
01297         if (!CheckFreeSpace(prefix.GetPath()))
01298         {
01299             return;
01300         };
01301 
01302 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01303                 wxString cmd = MacGetPathToMainExecutableFileOfRegisteredBundle(CFSTR("net.sourceforge.hugin.PTBatcherGUI"));
01304                 if(cmd != wxT(""))
01305                 { 
01306                         //Found PTBatcherGui inside the (registered) PTBatcherGui bundle. Call it directly.
01307                         //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
01308                         //will provide the menu
01309                         cmd = hugin_utils::wxQuoteString(cmd); 
01310             cmd += wxT(" ") + switches + hugin_utils::wxQuoteFilename(projectFile) + wxT(" ") + hugin_utils::wxQuoteFilename(dlg.GetPath());
01311                         wxExecute(cmd);
01312                 }
01313                 else
01314                 { //Can't find PTBatcherGui.app bundle. Use the most straightforward call possible to the bundle but this should actually not work either.
01315                                 wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
01316                 cmd = wxT("open -b net.sourceforge.hugin.PTBatcherGUI ")+hugin_utils::wxQuoteFilename(projectFile);
01317                                 wxExecute(cmd);
01318                 }
01319                 
01320 #else
01321         const wxFileName exePath(wxStandardPaths::Get().GetExecutablePath());
01322         wxExecute(exePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + wxT("PTBatcherGUI ") + switches + hugin_utils::wxQuoteFilename(projectFile) + wxT(" ") + hugin_utils::wxQuoteFilename(dlg.GetPath()));
01323 #endif
01324         HuginBase::LensDB::SaveLensDataFromPano(*pano);
01325     }
01326 };
01327 
01328 void PanoPanel::DoUserDefinedStitch(const wxString& settings)
01329 {
01330     if (pano->getNrOfImages() == 0)
01331     {
01332         return;
01333     }
01334 
01335     if (!CheckGoodSize())
01336     {
01337         // oversized pano and the user no longer wants to stitch.
01338         return;
01339     }
01340     if (!CheckHasImages())
01341     {
01342         // output ROI contains no images
01343         return;
01344     };
01345     wxFileName userOutputSequence;
01346     if (settings.IsEmpty())
01347     {
01348         // no filename given, ask user
01349         wxConfigBase* config = wxConfigBase::Get();
01350         wxString path = config->Read(wxT("/userDefinedOutputPath"), MainFrame::Get()->GetDataPath());
01351         wxFileDialog userOutputDlg(this, _("Select user defined output"),
01352             path, wxT(""), _("User defined output|*.executor"),
01353             wxFD_OPEN | wxFD_MULTIPLE | wxFD_FILE_MUST_EXIST, wxDefaultPosition);
01354         if (userOutputDlg.ShowModal() != wxID_OK)
01355         {
01356             return;
01357         };
01358         // remember path for later
01359         config->Write(wxT("/userDefinedOutputPath"), userOutputDlg.GetDirectory());
01360         userOutputSequence = userOutputDlg.GetPath();
01361     }
01362     else
01363     {
01364         //filename given, check existance
01365         userOutputSequence = settings;
01366         if (!userOutputSequence.Exists())
01367         {
01368             wxMessageBox(wxString::Format(wxT("User defined output %s not found.\nStopping processing."), userOutputSequence.GetFullPath()), _("Warning"), wxOK | wxICON_INFORMATION);
01369             return;
01370         };
01371     };
01372 
01373     // create a copy, if we need to update the crop setting
01374     // save project
01375     // copy pto file to temporary file
01376     wxString tempDir = wxConfigBase::Get()->Read(wxT("tempDir"), wxT(""));
01377     if (!tempDir.IsEmpty())
01378     {
01379         if (tempDir.Last() != wxFileName::GetPathSeparator())
01380         {
01381             tempDir.Append(wxFileName::GetPathSeparator());
01382         }
01383     };
01384     wxString currentPTOfn = wxFileName::CreateTempFileName(tempDir + wxT("huginpto_"));
01385     if (currentPTOfn.size() == 0)
01386     {
01387         wxMessageBox(_("Could not create temporary project file"), _("Error"),
01388             wxCANCEL | wxICON_ERROR, this);
01389         return;
01390     }
01391     DEBUG_DEBUG("tmp PTO file: " << (const char *)currentPTOfn.mb_str(wxConvLocal));
01392     // copy is not enough, need to adjust image path names...
01393     std::ofstream script(currentPTOfn.mb_str(HUGIN_CONV_FILENAME));
01394     HuginBase::UIntSet all;
01395     fill_set(all, 0, pano->getNrOfImages() - 1);
01396     pano->printPanoramaScript(script, pano->getOptimizeVector(), pano->getOptions(), all, false, "");
01397     script.close();
01398 
01399     //    wxCommandEvent dummy;
01400     //    MainFrame::Get()->OnSaveProject(dummy);
01401 
01402 #if defined __WXMAC__ && defined MAC_SELF_CONTAINED_BUNDLE
01403     // HuginStitchProject inside main bundle
01404     wxString hugin_stitch_project = MacGetPathToBundledAppMainExecutableFile(CFSTR("HuginStitchProject.app"));
01405     if (hugin_stitch_project == wxT(""))
01406     {
01407         DEBUG_ERROR("hugin_stitch_project could not be found in the bundle.");
01408         return;
01409     }
01410     hugin_stitch_project = hugin_utils::wxQuoteFilename(hugin_stitch_project);
01411 #elif defined __WXMAC__
01412     // HuginStitchProject installed in INSTALL_OSX_BUNDLE_DIR
01413     wxFileName hugin_stitch_project_app(wxT(INSTALL_OSX_BUNDLE_DIR), wxEmptyString);
01414     hugin_stitch_project_app.AppendDir(wxT("HuginStitchProject.app"));
01415     CFStringRef stitchProjectAppPath = MacCreateCFStringWithWxString(hugin_stitch_project_app.GetFullPath());
01416     wxString hugin_stitch_project = MacGetPathToMainExecutableFileOfBundle(stitchProjectAppPath);
01417     CFRelease(stitchProjectAppPath);
01418 #else
01419     wxString hugin_stitch_project = wxT("hugin_stitch_project");
01420 #endif
01421 
01422     // Derive a default output prefix from the project filename if set, otherwise default project filename
01423     wxFileName outputPrefix(getDefaultOutputName(MainFrame::Get()->getProjectName(), *pano));
01424     outputPrefix.Normalize();
01425 
01426     // Show a file save dialog so user can confirm/change the prefix.
01427     // (We don't have to worry about overwriting existing files, since hugin_switch_project checks this.)
01428     // TODO: The following code is similar to stitchApp::OnInit in hugin_switch_project.cpp. Should be refactored.
01429     // TODO: We should save the output prefix somewhere, so we can recall it as the default if the user stitches this project again.
01430     wxFileDialog dlg(this, _("Specify output prefix"),
01431         outputPrefix.GetPath(), outputPrefix.GetName(), wxT(""),
01432         wxFD_SAVE, wxDefaultPosition);
01433     if (dlg.ShowModal() != wxID_OK)
01434     {
01435         return;
01436     };
01437     while (containsInvalidCharacters(dlg.GetPath()))
01438     {
01439         wxArrayString list;
01440         list.Add(dlg.GetPath());
01441         ShowFilenameWarning(this, list);
01442         if (dlg.ShowModal() != wxID_OK)
01443             return;
01444     };
01445     wxFileName prefix(dlg.GetPath());
01446     while (!prefix.IsDirWritable())
01447     {
01448         wxMessageBox(wxString::Format(_("You have no permissions to write in folder \"%s\".\nPlease select another folder for the final output."), prefix.GetPath().c_str()),
01449 #ifdef __WXMSW__
01450             wxT("Hugin"),
01451 #else
01452             wxT(""),
01453 #endif
01454             wxOK | wxICON_INFORMATION);
01455         if (dlg.ShowModal() != wxID_OK)
01456         {
01457             return;
01458         };
01459         prefix = dlg.GetPath();
01460     };
01461     // check free space
01462     if (!CheckFreeSpace(prefix.GetPath()))
01463     {
01464         return;
01465     };
01466 
01467     wxString switches(wxT(" --user-defined-output=") + hugin_utils::wxQuoteFilename(userOutputSequence.GetFullPath()) + wxT(" --delete -o "));
01468     if (wxConfigBase::Get()->Read(wxT("/Processor/overwrite"), HUGIN_PROCESSOR_OVERWRITE) == 1)
01469         switches = wxT(" --overwrite") + switches;
01470     wxString command = hugin_stitch_project + switches + hugin_utils::wxQuoteFilename(dlg.GetPath()) + wxT(" ") + hugin_utils::wxQuoteFilename(currentPTOfn);
01471 
01472     wxConfigBase::Get()->Flush();
01473 #ifdef __WXGTK__
01474     // work around a wxExecute bug/problem
01475     // (endless polling of fd 0 and 1 in hugin_stitch_project)
01476     wxProcess *my_process = new wxProcess(this);
01477     my_process->Redirect();
01478 
01479     // Delete itself once processes terminated.
01480     my_process->Detach();
01481     wxExecute(command, wxEXEC_ASYNC, my_process);
01482 #else
01483     wxExecute(command);
01484 #endif
01485 }
01486 
01487 
01488 void PanoPanel::OnDoStitch ( wxCommandEvent & e )
01489 {
01490     long t;
01491     if(wxGetKeyState(WXK_COMMAND))
01492     {
01493         t=1;
01494     }
01495     else
01496     {
01497         wxConfigBase::Get()->Read(wxT("/Processor/gui"),&t,HUGIN_PROCESSOR_GUI);
01498     };
01499     switch (t)
01500     {
01501         // PTBatcher
01502         case 0:
01503             DoSendToBatch();
01504             break;
01505         // hugin_stitch_project
01506         case 1:
01507             DoStitch();
01508             break;
01509         // there is an error in the preferences
01510         default :
01511             // TODO: notify user and fix preferences misconfiguration
01512             break;
01513       }
01514 }
01515 
01516 void PanoPanel::FileFormatChanged(wxCommandEvent & e)
01517 {
01518 
01519     int fmt = m_FileFormatChoice->GetSelection();
01520     DEBUG_DEBUG("changing file format to " << fmt);
01521 
01522     HuginBase::PanoramaOptions opt = pano->getOptions();
01523     switch (fmt) {
01524         case 1:
01525             opt.outputImageType ="jpg";
01526             break;
01527         case 2:
01528             opt.outputImageType ="png";
01529             break;
01530         case 3:
01531             opt.outputImageType ="exr";
01532             break;
01533         default:
01534         case 0:
01535             opt.outputImageType ="tif";
01536             break;
01537     }
01538 
01539     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01540             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01541             );
01542 }
01543 
01544 void PanoPanel::HDRFileFormatChanged(wxCommandEvent & e)
01545 {
01546 
01547     int fmt = m_HDRFileFormatChoice->GetSelection();
01548     DEBUG_DEBUG("changing file format to " << fmt);
01549 
01550     HuginBase::PanoramaOptions opt = pano->getOptions();
01551     switch (fmt) {
01552         case 1:
01553             opt.outputImageTypeHDR ="tif";
01554             break;
01555         default:
01556         case 0:
01557             opt.outputImageTypeHDR ="exr";
01558             break;
01559     }
01560 
01561     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01562             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01563             );
01564 }
01565 
01566 void PanoPanel::OnJPEGQualityText(wxCommandEvent & e)
01567 {
01568     HuginBase::PanoramaOptions opt = pano->getOptions();
01569     long l = 100;
01570     m_FileFormatJPEGQualityText->GetValue().ToLong(&l);
01571     if (l < 0) l=1;
01572     if (l > 100) l=100;
01573     DEBUG_DEBUG("Setting jpeg quality to " << l);
01574     opt.quality = l;
01575     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01576             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01577             );
01578 }
01579 
01580 void PanoPanel::OnNormalTIFFCompression(wxCommandEvent & e)
01581 {
01582     HuginBase::PanoramaOptions opt = pano->getOptions();
01583     switch(e.GetSelection()) {
01584         case 0:
01585         default:
01586             opt.outputImageTypeCompression = "NONE";
01587             opt.tiffCompression = "NONE";
01588             break;
01589         case 1:
01590             opt.outputImageTypeCompression = "PACKBITS";
01591             opt.tiffCompression = "PACKBITS";
01592             break;
01593         case 2:
01594             opt.outputImageTypeCompression = "LZW";
01595             opt.tiffCompression = "LZW";
01596             break;
01597         case 3:
01598             opt.outputImageTypeCompression = "DEFLATE";
01599             opt.tiffCompression = "DEFLATE";
01600             break;
01601     }
01602     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01603             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01604             );
01605 }
01606 
01607 void PanoPanel::OnHDRTIFFCompression(wxCommandEvent & e)
01608 {
01609     HuginBase::PanoramaOptions opt = pano->getOptions();
01610     switch(e.GetSelection()) {
01611         case 0:
01612         default:
01613             opt.outputImageTypeHDRCompression = "NONE";
01614             break;
01615         case 1:
01616             opt.outputImageTypeHDRCompression = "PACKBITS";
01617             break;
01618         case 2:
01619             opt.outputImageTypeHDRCompression = "LZW";
01620             break;
01621         case 3:
01622             opt.outputImageTypeHDRCompression = "DEFLATE";
01623             break;
01624     }
01625     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01626             new PanoCommand::SetPanoOptionsCmd( *pano, opt )
01627             );
01628 }
01629 
01630 void PanoPanel::OnOutputFilesChanged(wxCommandEvent & e)
01631 {
01632     int id = e.GetId();
01633     HuginBase::PanoramaOptions opts = pano->getOptions();
01634 
01635     if (id == XRCID("pano_cb_ldr_output_blended") ) {
01636         opts.outputLDRBlended = e.IsChecked();
01637     } else if (id == XRCID("pano_cb_ldr_output_layers") ) {
01638         opts.outputLDRLayers = e.IsChecked();
01639     } else if (id == XRCID("pano_cb_ldr_output_exposure_layers") ) {
01640         opts.outputLDRExposureLayers = e.IsChecked();
01641     } else if (id == XRCID("pano_cb_ldr_output_exposure_blended") ) {
01642         opts.outputLDRExposureBlended = e.IsChecked();
01643     } else if (id == XRCID("pano_cb_ldr_output_exposure_layers_fused") ) {
01644         opts.outputLDRExposureLayersFused = e.IsChecked();
01645     } else if (id == XRCID("pano_cb_ldr_output_exposure_remapped") ) {
01646         opts.outputLDRExposureRemapped = e.IsChecked();
01647     } else if (id == XRCID("pano_cb_ldr_output_stacks") ) {
01648         opts.outputLDRStacks = e.IsChecked();
01649     } else if (id == XRCID("pano_cb_hdr_output_blended") ) {
01650         opts.outputHDRBlended = e.IsChecked();
01651     } else if (id == XRCID("pano_cb_hdr_output_stacks") ) {
01652         opts.outputHDRStacks = e.IsChecked();
01653     } else if (id == XRCID("pano_cb_hdr_output_layers") ) {
01654         opts.outputHDRLayers = e.IsChecked();
01655     }
01656     
01657     PanoCommand::GlobalCmdHist::getInstance().addCommand(
01658             new PanoCommand::SetPanoOptionsCmd( *pano, opts )
01659         );
01660 }
01661 
01662 bool PanoPanel::CheckGoodSize()
01663 {
01664     const HuginBase::PanoramaOptions opts(pano->getOptions());
01665     const vigra::Rect2D cropped_region (opts.getROI());    
01666     // width and height of jpeg images has to be smaller than 65500 pixel
01667     if (opts.outputImageType == "jpg" &&
01668         (opts.outputLDRBlended || opts.outputLDRExposureBlended || opts.outputLDRExposureLayersFused) &&
01669         (cropped_region.width()>65500 || cropped_region.height()>65500)
01670         )
01671     {
01672         wxMessageBox(
01673             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()),
01674 #ifdef _WIN32
01675             _("Hugin"),
01676 #else
01677             wxT(""),
01678 #endif
01679             wxICON_EXCLAMATION | wxOK);
01680         return false;
01681     };
01682     wxString message;
01683     unsigned long long int area = ((unsigned long int) cropped_region.width()) * ((unsigned long int) cropped_region.height());
01684     // Argh, more than half a gigapixel!
01685     if (area > 500000000)
01686     {
01687         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."),
01688             area / 1000000000.0);
01689     }
01690     else
01691     {
01692         if (cropped_region.width() > 32700 || cropped_region.height() > 32700)
01693         {
01694             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.");
01695         };
01696     };
01697     if (!message.empty())
01698     {
01699         // Tell the user the stitch will be really big, and give them a
01700         // chance to reduce the size.
01701         wxMessageDialog dialog(this,
01702                 _("Are you sure you want to stitch such a large panorama?"),
01703 #ifdef _WIN32
01704                 _("Hugin"),
01705 #else
01706                 wxT(""),
01707 #endif
01708                 wxICON_EXCLAMATION | wxYES_NO);
01709         dialog.SetExtendedMessage(message);
01710         dialog.SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
01711         switch (dialog.ShowModal())
01712         {
01713             case wxID_OK:
01714             case wxID_YES:
01715                 // Continue stitch.
01716                 return true;
01717                 break;
01718             default:
01719                 // bring the user towards the approptiate controls.
01720                 MainFrame* mainframe = MainFrame::Get();
01721                 if (!mainframe->IsShown())
01722                 {
01723                     mainframe->Show();
01724                 }
01725                 mainframe->ShowStitcherTab();
01726                 return false;
01727         }
01728     }
01729     // I see nothing wrong with this...
01730     return true;
01731 }
01732 
01733 bool PanoPanel::CheckHasImages()
01734 {
01735     HuginBase::UIntSet images=getImagesinROI(*pano, pano->getActiveImages());
01736     if(images.size()==0)
01737     {
01738         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."),
01739 #ifdef _WIN32
01740             _("Hugin"),
01741 #else
01742             wxT(""),
01743 #endif
01744             wxOK | wxICON_INFORMATION);
01745     };
01746     return images.size()>0;
01747 };
01748 
01749 bool PanoPanel::CheckFreeSpace(const wxString& folder)
01750 {
01751     wxLongLong freeSpace;
01752     if (wxGetDiskSpace(folder, NULL, &freeSpace))
01753     {
01754         // 4 channels, 16 bit per channel, assuming the we need the 10 fold space for all temporary space
01755         if (pano->getOptions().getROI().area() * 80 > freeSpace)
01756         {
01757             wxMessageDialog dialog(this,
01758                 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),
01759 #ifdef _WIN32
01760                 _("Hugin"),
01761 #else
01762                 wxT(""),
01763 #endif
01764                 wxICON_EXCLAMATION | wxYES_NO);
01765             dialog.SetYesNoLabels(_("Stitch anyway"), _("Let me fix that"));
01766             if (dialog.ShowModal() == wxID_NO)
01767             {
01768                 // bring the user towards the approptiate controls.
01769                 MainFrame* mainframe = MainFrame::Get();
01770                 if (!mainframe->IsShown())
01771                 {
01772                     mainframe->Show();
01773                 }
01774                 mainframe->ShowStitcherTab();
01775                 return false;
01776             };
01777         };
01778     };
01779     return true;
01780 };
01781 
01782 void PanoPanel::SetGuiLevel(GuiLevel newGuiLevel)
01783 {
01784     m_guiLevel=newGuiLevel;
01785     UpdateDisplay(m_oldOpt, false);
01786 };
01787 
01788 IMPLEMENT_DYNAMIC_CLASS(PanoPanel, wxPanel)
01789 
01790 PanoPanelXmlHandler::PanoPanelXmlHandler()
01791                 : wxXmlResourceHandler()
01792 {
01793     AddWindowStyles();
01794 }
01795 
01796 wxObject *PanoPanelXmlHandler::DoCreateResource()
01797 {
01798     XRC_MAKE_INSTANCE(cp, PanoPanel)
01799 
01800     cp->Create(m_parentAsWindow,
01801                    GetID(),
01802                    GetPosition(), GetSize(),
01803                    GetStyle(wxT("style")),
01804                    GetName());
01805 
01806     SetupWindow( cp);
01807 
01808     return cp;
01809 }
01810 
01811 bool PanoPanelXmlHandler::CanHandle(wxXmlNode *node)
01812 {
01813     return IsOfClass(node, wxT("PanoPanel"));
01814 }
01815 
01816 IMPLEMENT_DYNAMIC_CLASS(PanoPanelXmlHandler, wxXmlResourceHandler)
01817 

Generated on 24 Sep 2017 for Hugintrunk by  doxygen 1.4.7