PanoPanel.cpp

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

Generated on Thu Apr 17 01:25:37 2014 for Hugintrunk by  doxygen 1.3.9.1