Hugintrunk  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GLPreviewFrame.cpp
Go to the documentation of this file.
1 // -*- c-basic-offset: 4 -*-
2 
26 #include <bitset>
27 #include <limits>
28 #include <iostream>
29 
30 #include "hugin_config.h"
31 
32 #if !defined HAVE_EPOXY || !HAVE_EPOXY
33 #include <GL/glew.h>
34 #endif
35 
36 #include "panoinc_WX.h"
37 #include "panoinc.h"
38 #include <wx/msgdlg.h>
39 
40 #include "base_wx/platform.h"
41 #include "base_wx/wxPlatform.h"
42 #include "base_wx/LensTools.h"
49 
51 #include "base_wx/wxPanoCommand.h"
52 
53 #include "hugin/config_defaults.h"
54 #include "hugin/GLPreviewFrame.h"
55 #include "hugin/huginApp.h"
56 #include "hugin/MainFrame.h"
57 #include "hugin/ImagesPanel.h"
58 #include "base_wx/CommandHistory.h"
59 #include "hugin/GLViewer.h"
61 #include "hugin/PanoOperation.h"
62 #include "hugin/PanoOutputDialog.h"
64 #include "base_wx/PTWXDlg.h"
66 #include "vigra_ext/Correlation.h"
69 
70 extern "C" {
71 #include <pano13/queryfeature.h>
72 }
73 
74 #include "ToolHelper.h"
75 #include "Tool.h"
76 #include "DragTool.h"
77 #include "PreviewCropTool.h"
78 #include "PreviewIdentifyTool.h"
79 #include "PreviewCameraTool.h"
80 #include "PreviewDifferenceTool.h"
81 #include "PreviewPanoMaskTool.h"
83 #include "PreviewLayoutLinesTool.h"
84 #include "PreviewColorPickerTool.h"
85 #include "PreviewGuideTool.h"
86 #include "PreviewEditCPTool.h"
87 
88 #include "ProjectionGridTool.h"
89 #include "PanosphereSphereTool.h"
90 
91 #include "OverviewCameraTool.h"
92 #include "OverviewOutlinesTool.h"
93 
94 #include <wx/progdlg.h>
95 #include <wx/infobar.h>
96 
97 // a random id, hope this doesn't break something..
98 enum {
99  ID_TOGGLE_BUT = wxID_HIGHEST+500,
100  PROJ_PARAM_NAMES_ID = wxID_HIGHEST+1300,
101  PROJ_PARAM_VAL_ID = wxID_HIGHEST+1400,
102  PROJ_PARAM_SLIDER_ID = wxID_HIGHEST+1500,
103  PROJ_PARAM_RESET_ID = wxID_HIGHEST+1550,
104  ID_TOGGLE_BUT_LEAVE = wxID_HIGHEST+1600,
105  ID_FULL_SCREEN = wxID_HIGHEST+1710,
106  ID_SHOW_ALL = wxID_HIGHEST+1711,
107  ID_SHOW_NONE = wxID_HIGHEST+1712,
108  ID_HIDE_HINTS = wxID_HIGHEST+1715,
109  ID_ASSISTANT_MENU = wxID_HIGHEST+1800,
110  ID_CREATEPANO_MENU = wxID_HIGHEST+1810,
111  ID_ASS_LOAD_IMAGES = wxID_HIGHEST+1820
112 };
113 
115 enum{
122 };
123 
124 //------------------------------------------------------------------------------
125 BEGIN_EVENT_TABLE(GLwxAuiFloatingFrame, wxAuiFloatingFrame)
126  EVT_ACTIVATE(GLwxAuiFloatingFrame::OnActivate)
128 
129 BEGIN_EVENT_TABLE(GLPreviewFrame, wxFrame)
130  EVT_CLOSE(GLPreviewFrame::OnClose)
131  EVT_SHOW(GLPreviewFrame::OnShowEvent)
132  //for some reason only key up is sent, key down event is not sent
133 // EVT_KEY_DOWN(GLPreviewFrame::KeyDown)
134 // EVT_KEY_UP(GLPreviewFrame::KeyUp)
135  EVT_BUTTON(XRCID("preview_center_tool"), GLPreviewFrame::OnCenterHorizontally)
136  EVT_BUTTON(XRCID("preview_fit_pano_tool"), GLPreviewFrame::OnFitPano)
137  EVT_BUTTON(XRCID("preview_fit_pano_tool2"), GLPreviewFrame::OnFitPano)
138  EVT_BUTTON(XRCID("preview_straighten_pano_tool"), GLPreviewFrame::OnStraighten)
139  EVT_BUTTON(XRCID("apply_num_transform"), GLPreviewFrame::OnNumTransform)
140  EVT_TEXT_ENTER(XRCID("input_yaw"), GLPreviewFrame::OnNumTransform)
141  EVT_TEXT_ENTER(XRCID("input_pitch"), GLPreviewFrame::OnNumTransform)
142  EVT_TEXT_ENTER(XRCID("input_roll"), GLPreviewFrame::OnNumTransform)
143  EVT_TEXT_ENTER(XRCID("input_x"), GLPreviewFrame::OnNumTransform)
144  EVT_TEXT_ENTER(XRCID("input_y"), GLPreviewFrame::OnNumTransform)
145  EVT_TEXT_ENTER(XRCID("input_z"), GLPreviewFrame::OnNumTransform)
146  EVT_BUTTON(ID_SHOW_ALL, GLPreviewFrame::OnShowAll)
147  EVT_BUTTON(ID_SHOW_NONE, GLPreviewFrame::OnShowNone)
148  EVT_CHECKBOX(XRCID("preview_photometric_tool"), GLPreviewFrame::OnPhotometric)
149  EVT_TOGGLEBUTTON(XRCID("preview_identify_toggle_button"), GLPreviewFrame::OnIdentify)
150  EVT_TOGGLEBUTTON(XRCID("preview_color_picker_toggle_button"), GLPreviewFrame::OnColorPicker)
151  EVT_TOGGLEBUTTON(XRCID("preview_edit_cp_toggle_button"), GLPreviewFrame::OnEditCPTool)
152  EVT_CHECKBOX(XRCID("preview_control_point_tool"), GLPreviewFrame::OnControlPoint)
153  EVT_BUTTON(XRCID("preview_autocrop_tool"), GLPreviewFrame::OnAutocrop)
154  EVT_BUTTON(XRCID("preview_stack_autocrop_tool"), GLPreviewFrame::OnStackAutocrop)
155  EVT_BUTTON(XRCID("preview_autocrop_outside_tool"), GLPreviewFrame::OnAutocropOutside)
156  EVT_NOTEBOOK_PAGE_CHANGED(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnSelectMode)
157  EVT_NOTEBOOK_PAGE_CHANGING(XRCID("mode_toolbar_notebook"), GLPreviewFrame::OnToolModeChanging)
158  EVT_BUTTON(ID_HIDE_HINTS, GLPreviewFrame::OnHideProjectionHints)
159  EVT_BUTTON(XRCID("exposure_default_button"), GLPreviewFrame::OnDefaultExposure)
160  EVT_SPIN_DOWN(XRCID("exposure_spin"), GLPreviewFrame::OnDecreaseExposure)
161  EVT_SPIN_UP(XRCID("exposure_spin"), GLPreviewFrame::OnIncreaseExposure)
162  EVT_SPIN_DOWN(XRCID("range_compression_spin"), GLPreviewFrame::OnRangeCompressionDecrease)
163  EVT_SPIN_UP(XRCID("range_compression_spin"), GLPreviewFrame::OnRangeCompressionIncrease)
164  EVT_TEXT_ENTER(XRCID("range_compression_text"), GLPreviewFrame::OnRangeCompressionChanged)
165  EVT_CHOICE(XRCID("blend_mode_choice"), GLPreviewFrame::OnBlendChoice)
166  EVT_CHOICE(XRCID("drag_mode_choice"), GLPreviewFrame::OnDragChoice)
167  EVT_CHOICE(XRCID("projection_choice"), GLPreviewFrame::OnProjectionChoice)
168  EVT_CHOICE(XRCID("overview_mode_choice"), GLPreviewFrame::OnOverviewModeChoice)
169  EVT_CHOICE(XRCID("preview_guide_choice_crop"), GLPreviewFrame::OnGuideChanged)
170  EVT_CHOICE(XRCID("preview_guide_choice_drag"), GLPreviewFrame::OnGuideChanged)
171  EVT_CHOICE(XRCID("preview_guide_choice_proj"), GLPreviewFrame::OnGuideChanged)
172  EVT_MENU(XRCID("action_show_overview"), GLPreviewFrame::OnOverviewToggle)
173  EVT_MENU(XRCID("action_show_grid"), GLPreviewFrame::OnSwitchPreviewGrid)
174  EVT_MENU(ID_CREATE_CP, GLPreviewFrame::OnCreateCP)
175  EVT_MENU(ID_REMOVE_CP, GLPreviewFrame::OnRemoveCP)
176  EVT_MENU_CLOSE(GLPreviewFrame::OnMenuClose)
177 #ifndef __WXMAC__
178  EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
179  EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
180  EVT_COMMAND_SCROLL_CHANGED(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
181 #else
182  EVT_SCROLL_THUMBRELEASE(GLPreviewFrame::OnChangeFOV)
183  EVT_COMMAND_SCROLL(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
184  EVT_SCROLL_CHANGED(GLPreviewFrame::OnChangeFOV)
185  EVT_COMMAND_SCROLL_THUMBTRACK(XRCID("layout_scale_slider"), GLPreviewFrame::OnLayoutScaleChange)
186 #endif
187  EVT_SCROLL_THUMBTRACK(GLPreviewFrame::OnTrackChangeFOV)
188  EVT_TEXT_ENTER(XRCID("pano_text_hfov"), GLPreviewFrame::OnHFOVChanged )
189  EVT_TEXT_ENTER(XRCID("pano_text_vfov"), GLPreviewFrame::OnVFOVChanged )
190  EVT_TEXT_ENTER(XRCID("pano_val_roi_left"), GLPreviewFrame::OnROIChanged)
191  EVT_TEXT_ENTER(XRCID("pano_val_roi_top"), GLPreviewFrame::OnROIChanged)
192  EVT_TEXT_ENTER(XRCID("pano_val_roi_right"), GLPreviewFrame::OnROIChanged)
193  EVT_TEXT_ENTER(XRCID("pano_val_roi_bottom"), GLPreviewFrame::OnROIChanged)
194  EVT_BUTTON(XRCID("reset_crop_button"), GLPreviewFrame::OnResetCrop)
195  EVT_BUTTON(XRCID("crop_aspect_button"), GLPreviewFrame::OnSetCropAspect)
196  EVT_TEXT_ENTER(XRCID("exposure_text"), GLPreviewFrame::OnExposureChanged)
197  EVT_COMMAND_RANGE(PROJ_PARAM_VAL_ID,PROJ_PARAM_VAL_ID+PANO_PROJECTION_MAX_PARMS,wxEVT_COMMAND_TEXT_ENTER,GLPreviewFrame::OnProjParameterChanged)
198  EVT_BUTTON(PROJ_PARAM_RESET_ID, GLPreviewFrame::OnProjParameterReset)
199  EVT_TOOL(ID_FULL_SCREEN, GLPreviewFrame::OnFullScreen)
200  EVT_COLOURPICKER_CHANGED(XRCID("preview_background"), GLPreviewFrame::OnPreviewBackgroundColorChanged)
201  EVT_MENU(XRCID("ID_SHOW_FULL_SCREEN_PREVIEW"), GLPreviewFrame::OnFullScreen)
202  EVT_MENU(XRCID("action_show_main_frame"), GLPreviewFrame::OnShowMainFrame)
203  EVT_MENU(XRCID("action_exit_preview"), GLPreviewFrame::OnUserExit)
204  EVT_BUTTON ( XRCID("ass_load_images_button"), GLPreviewFrame::OnLoadImages)
205  EVT_BUTTON ( XRCID("ass_align_button"), GLPreviewFrame::OnAlign)
206  EVT_BUTTON ( XRCID("ass_create_button"), GLPreviewFrame::OnCreate)
207  // context menu of select all button
208  EVT_MENU(XRCID("selectMenu_selectAll"), GLPreviewFrame::OnSelectAllMenu)
209  EVT_MENU(XRCID("selectMenu_selectMedian"), GLPreviewFrame::OnSelectMedianMenu)
210  EVT_MENU(XRCID("selectMenu_selectBrightest"), GLPreviewFrame::OnSelectDarkestMenu)
211  EVT_MENU(XRCID("selectMenu_selectDarkest"), GLPreviewFrame::OnSelectBrightestMenu)
212  EVT_MENU(XRCID("selectMenu_keepCurrentSelection"), GLPreviewFrame::OnSelectKeepSelection)
213  EVT_MENU(XRCID("selectMenu_resetSelection"), GLPreviewFrame::OnSelectResetSelection)
215 
216 BEGIN_EVENT_TABLE(ImageToogleButtonEventHandler, wxEvtHandler)
217  EVT_ENTER_WINDOW(ImageToogleButtonEventHandler::OnEnter)
218  EVT_LEAVE_WINDOW(ImageToogleButtonEventHandler::OnLeave)
219  EVT_TOGGLEBUTTON(-1, ImageToogleButtonEventHandler::OnChange)
221 
222 BEGIN_EVENT_TABLE(ImageGroupButtonEventHandler, wxEvtHandler)
223  EVT_ENTER_WINDOW(ImageGroupButtonEventHandler::OnEnter)
224  EVT_LEAVE_WINDOW(ImageGroupButtonEventHandler::OnLeave)
225  EVT_CHECKBOX(-1, ImageGroupButtonEventHandler::OnChange)
227 
228 #define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
229 GLwxAuiFloatingFrame* GLwxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p)
230 {
231  DEBUG_DEBUG("CREATING FLOATING FRAME");
232  frame->PauseResize();
233  GLwxAuiFloatingFrame* fl_frame = new GLwxAuiFloatingFrame(parent, this, p);
234  DEBUG_DEBUG("CREATED FLOATING FRAME");
235  return fl_frame;
236 }
237 
238 void GLwxAuiFloatingFrame::OnActivate(wxActivateEvent& evt)
239 {
240  DEBUG_DEBUG("FRAME ACTIVATE");
241  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
242  frame->ContinueResize();
243  evt.Skip();
244 }
245 
247 {
248  DEBUG_DEBUG("FRAME ON MOVE FINISHED");
249  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
250  frame->PauseResize();
251  wxAuiFloatingFrame::OnMoveFinished();
252  DEBUG_DEBUG("FRAME AFTER ON MOVE FINISHED");
253 }
254 
256 {
257  DEBUG_DEBUG("PAUSE RESIZE");
258  GLresize = false;
259 }
260 
262 {
263  GLresize = true;
264  wxSizeEvent event = wxSizeEvent(wxSize());
265  m_GLPreview->Resized(event);
266  m_GLOverview->Resized(event);
267 }
268 
269 #include <iostream>
271  : wxFrame(frame,-1, _("Fast Panorama preview"), wxDefaultPosition, wxDefaultSize,
272  PF_STYLE),
273  m_pano(pano)
274 {
275 
276  DEBUG_TRACE("");
277 
278  // initialize pointer
279  preview_helper = NULL;
281  plane_overview_helper = NULL;
282  crop_tool = NULL;
283  drag_tool = NULL;
284  color_picker_tool = NULL;
285  edit_cp_tool = NULL;
286  overview_drag_tool = NULL;
287  identify_tool = NULL ;
288  camera_tool = NULL;
291  difference_tool = NULL;
292  plane_difference_tool = NULL;
294  pano_mask_tool = NULL;
295  preview_guide_tool = NULL;
297 #ifdef __WXGTK__
298  loadedLayout=false;
299 #endif
300 
301  m_mode = -1;
302  m_oldProjFormat = -1;
303  // add a status bar
304  CreateStatusBar(3);
305  int widths[3] = {-3, 150, 150};
306  SetStatusWidths(3, widths);
307  SetStatusText(wxT(""),1);
308  SetStatusText(wxT(""),2);
309  wxConfigBase * cfg = wxConfigBase::Get();
310 
311  wxPanel *tool_panel = wxXmlResource::Get()->LoadPanel(this,wxT("mode_panel"));
312  XRCCTRL(*this,"preview_center_tool",wxButton)->SetBitmapMargins(0,5);
313  XRCCTRL(*this,"preview_fit_pano_tool",wxButton)->SetBitmapMargins(0,5);
314  XRCCTRL(*this,"preview_straighten_pano_tool",wxButton)->SetBitmapMargins(0,5);
315  XRCCTRL(*this,"preview_fit_pano_tool2",wxButton)->SetBitmapMargins(0,5);
316  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
317  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
318  XRCCTRL(*this, "preview_autocrop_outside_tool", wxButton)->SetBitmapMargins(0, 5);
319 
320  m_tool_notebook = XRCCTRL(*this, "mode_toolbar_notebook", wxNotebook);
321  m_identify_togglebutton = XRCCTRL(*this, "preview_identify_toggle_button", wxToggleButton);
322  m_identify_togglebutton->SetBitmapMargins(0, 5);
323  m_colorpicker_togglebutton = XRCCTRL(*this, "preview_color_picker_toggle_button", wxToggleButton);
324  m_colorpicker_togglebutton->SetBitmapMargins(0, 5);
325  m_editCP_togglebutton = XRCCTRL(*this, "preview_edit_cp_toggle_button", wxToggleButton);
326  m_editCP_togglebutton->SetBitmapMargins(0, 5);
327  wxBitmap bitmap;
328 
329  //build menu bar
330 #ifdef __WXMAC__
331  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
332 #endif
333  wxMenuBar* simpleMenu=wxXmlResource::Get()->LoadMenuBar(this, wxT("preview_simple_menu"));
334  m_filemenuSimple=wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu"));
335  m_filemenuAdvanced = wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu_advanced"));
336  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuSimple->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
337  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuAdvanced->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
338  MainFrame::Get()->GetFileHistory()->AddFilesToMenu();
339  simpleMenu->Insert(0, m_filemenuSimple, _("&File"));
340  SetMenuBar(simpleMenu);
341 
342  // initialize preview background color
343  wxString c = cfg->Read(wxT("/GLPreviewFrame/PreviewBackground"),wxT(HUGIN_PREVIEW_BACKGROUND));
344  m_preview_background_color = wxColour(c);
345  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->SetColour(m_preview_background_color);
346  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Refresh();
347  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Update();
348 
349  m_topsizer = new wxBoxSizer( wxVERTICAL );
350 
351  wxPanel * toggle_panel = new wxPanel(this);
352 
353  bool overview_hidden;
354  cfg->Read(wxT("/GLPreviewFrame/overview_hidden"), &overview_hidden, false);
355  GetMenuBar()->FindItem(XRCID("action_show_overview"))->Check(!overview_hidden);
356 
357  m_ToggleButtonSizer = new wxStaticBoxSizer(
358  new wxStaticBox(toggle_panel, -1, _("displayed images")),
359  wxHORIZONTAL );
360  toggle_panel->SetSizer(m_ToggleButtonSizer);
361 
362  m_ButtonPanel = new wxScrolledWindow(toggle_panel, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
363  //Horizontal scroll bars only
364  m_ButtonPanel->SetScrollRate(10, 0);
365  m_ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
366  m_ButtonPanel->SetAutoLayout(true);
367  m_ButtonPanel->SetSizer(m_ButtonSizer);
368 
369  wxPanel *panel = new wxPanel(toggle_panel);
370  bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_all.png"),wxBITMAP_TYPE_PNG);
371  m_selectAllButton = new SplitButton(panel, ID_SHOW_ALL, _("All"), wxDefaultPosition, wxDefaultSize);
372  m_selectAllButton->SetBitmap(bitmap);
373  //m_selectAllButton->SetBitmapMargins(5, 0);
374  m_selectAllButton->LoadMenu(wxT("preview_select_menu"));
375  // read last used setting
376  long mode = cfg->Read(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
377  m_selectAllMode = static_cast<SelectAllMode>(mode);
378  switch (m_selectAllMode)
379  {
381  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectMedian"), true);
382  break;
384  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectDarkest"), true);
385  break;
387  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectBrightest"), true);
388  break;
389  case SELECT_ALL_IMAGES:
390  default:
391  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectAll"), true);
392  break;
393  };
394  m_selectKeepSelection = (cfg->Read(wxT("/GLPreviewFrame/SelectAllKeepSelection"), 1l) == 1l);
396  {
397  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_keepCurrentSelection"), true);
398  }
399  else
400  {
401  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_resetSelection"), true);
402  };
403  bitmap.LoadFile(huginApp::Get()->GetXRCPath()+wxT("data/preview_show_none.png"),wxBITMAP_TYPE_PNG);
404  wxButton* select_none = new wxButton(panel, ID_SHOW_NONE, _("None"));
405  select_none->SetBitmap(bitmap,wxLEFT);
406  select_none->SetBitmapMargins(5,0);
407 
408  wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
409  sizer->Add(m_selectAllButton,0,wxALIGN_CENTER_VERTICAL | wxLEFT | wxTOP | wxBOTTOM,5);
410  sizer->Add(select_none,0,wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP | wxBOTTOM,5);
411  panel->SetSizer(sizer);
412  m_ToggleButtonSizer->Add(panel, 0, wxALIGN_CENTER_VERTICAL);
413  m_ToggleButtonSizer->Add(m_ButtonPanel, 1, wxALIGN_CENTER_VERTICAL, 0);
414 
415  m_topsizer->Add(tool_panel, 0, wxEXPAND | wxALL, 2);
416  m_topsizer->Add(toggle_panel, 0, wxEXPAND | wxBOTTOM, 5);
417 
418  m_infoBar = new wxInfoBar(this);
419  m_infoBar->AddButton(ID_HIDE_HINTS,_("Hide"));
420  m_infoBar->Connect(ID_HIDE_HINTS,wxEVT_COMMAND_BUTTON_CLICKED,wxCommandEventHandler(GLPreviewFrame::OnHideProjectionHints),NULL,this);
421  m_topsizer->Add(m_infoBar, 0, wxEXPAND);
422 
423  //create panel that will hold gl canvases
424  wxPanel * vis_panel = new wxPanel(this);
425 
426  wxPanel * preview_panel = new wxPanel(vis_panel);
427  wxPanel * overview_panel = new wxPanel(vis_panel);
428 
429  // create our Viewers
430  int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
431  m_GLPreview = new GLPreview(preview_panel, pano, args, this);
432  m_GLOverview = new GLOverview(overview_panel, pano, args, this, m_GLPreview->GetContext());
434 
435 #ifdef __WXGTK__
436  // on wxGTK we can not create the OpenGL context with a hidden window
437  // therefore we need to create the overview window open and later hide it
438  overview_hidden=false;
439 #endif
440  m_GLOverview->SetActive(!overview_hidden);
441 
442  // set the AUI manager to our panel
444  m_mgr->SetManagedWindow(vis_panel);
445  vis_panel->SetMinSize(wxSize(200,150));
446 
447  //create the sizer for the preview
448  wxFlexGridSizer * flexSizer = new wxFlexGridSizer(2,0,5,5);
449  flexSizer->AddGrowableCol(0);
450  flexSizer->AddGrowableRow(0);
451 
452  //overview sizer
453  wxBoxSizer * overview_sizer = new wxBoxSizer(wxVERTICAL);
454 
455 
456  flexSizer->Add(m_GLPreview,
457  1, // not vertically stretchable
458  wxEXPAND | // horizontally stretchable
459  wxALL, // draw border all around
460  5); // border width
461 
462  m_VFOVSlider = new wxSlider(preview_panel, -1, 1,
463  1, 180,
464  wxDefaultPosition, wxDefaultSize,
465  wxSL_VERTICAL | wxSL_AUTOTICKS,
466  wxDefaultValidator,
467  _("VFOV"));
468  m_VFOVSlider->SetLineSize(1);
469  m_VFOVSlider->SetPageSize(10);
470  m_VFOVSlider->SetTickFreq(5);
471  m_VFOVSlider->SetToolTip(_("drag to change the vertical field of view"));
472 
473  flexSizer->Add(m_VFOVSlider, 0, wxEXPAND);
474 
475  m_HFOVSlider = new wxSlider(preview_panel, -1, 1,
476  1, 360,
477  wxDefaultPosition, wxDefaultSize,
478  wxSL_HORIZONTAL | wxSL_AUTOTICKS,
479  wxDefaultValidator,
480  _("HFOV"));
481  m_HFOVSlider->SetPageSize(10);
482  m_HFOVSlider->SetLineSize(1);
483  m_HFOVSlider->SetTickFreq(5);
484 
485  m_HFOVSlider->SetToolTip(_("drag to change the horizontal field of view"));
486 
487  m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
489  m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
490  m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
492  m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
493 
494  m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
496  m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
497 
498  m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
500  m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
501 
502  m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
504  m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
505 
506  m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
508  m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
509 
510  m_GuideChoiceCrop = XRCCTRL(*this, "preview_guide_choice_crop", wxChoice);
511  m_GuideChoiceProj = XRCCTRL(*this, "preview_guide_choice_proj", wxChoice);
512  m_GuideChoiceDrag = XRCCTRL(*this, "preview_guide_choice_drag", wxChoice);
513  int guide=cfg->Read(wxT("/GLPreviewFrame/guide"),0l);
514  m_GuideChoiceCrop->SetSelection(guide);
515  m_GuideChoiceProj->SetSelection(guide);
516  m_GuideChoiceDrag->SetSelection(guide);
517 
518  flexSizer->Add(m_HFOVSlider, 0, wxEXPAND);
519 
520  m_overviewCommandPanel = wxXmlResource::Get()->LoadPanel(overview_panel,wxT("overview_command_panel"));
521  m_OverviewModeChoice = XRCCTRL(*this, "overview_mode_choice", wxChoice);
522  const wxSize dpiSize(m_overviewCommandPanel->FromDIP(wxSize(200, 20)));
523  m_overviewCommandPanel->SetSize(0, 0, dpiSize.GetWidth(), dpiSize.GetHeight(), wxSIZE_AUTO_WIDTH);
524 
525  overview_sizer->Add(m_overviewCommandPanel, 0, wxEXPAND);
526  overview_sizer->Add(m_GLOverview, 1, wxEXPAND);
527 
528  bool showGrid;
529  cfg->Read(wxT("/GLPreviewFrame/showPreviewGrid"),&showGrid,true);
530  GetMenuBar()->FindItem(XRCID("action_show_grid"))->Check(showGrid);
531 
532  preview_panel->SetSizer(flexSizer);
533  overview_panel->SetSizer(overview_sizer);
534 
535  m_mgr->AddPane(preview_panel,
536  wxAuiPaneInfo(
537  ).Name(wxT("preview")
538  ).MinSize(300,200
539  ).CloseButton(false
540  ).CaptionVisible(false
541  ).Caption(_("Preview")
542  ).Floatable(false
543  ).Dockable(false
544  ).Center(
545  )
546  );
547 
548  m_mgr->AddPane(overview_panel,
549  wxAuiPaneInfo(
550  ).Name(wxT("overview")
551  ).MinSize(300,200
552  ).CloseButton(false
553  ).CaptionVisible(
554  ).Caption(_("Overview")
555  ).FloatingSize(100,100
556  ).FloatingPosition(500,500
557  ).Dockable(true
558  ).PinButton(
559  ).Left(
560  ).Show(!overview_hidden
561  )
562  );
563 
564 
565  m_topsizer->Add(vis_panel, 1, wxEXPAND);
566 
567  //assistant related controls
568  m_loadImagesButton = XRCCTRL(*this, "ass_load_images_button", SplitButton);
570  m_loadImagesButton->GetSplitButtonMenu()->Append(ID_ASS_LOAD_IMAGES, _("Load images (autodetect lens type)..."));
571  Bind(wxEVT_MENU, &GLPreviewFrame::OnLoadImages, this, ID_ASS_LOAD_IMAGES);
572  m_loadImagesButton->GetSplitButtonMenu()->AppendSeparator();
573  // now add all lens types to menu
575  int lensTypeId = ID_ASS_LOAD_IMAGES + 1;
576  for (auto& lensType : lensInfoVector)
577  {
578  m_loadImagesButton->GetSplitButtonMenu()->Append(lensTypeId, wxString::Format(_("Load images (lens type: %s)..."), lensType.name));
579  const int lensId = lensType.id;
580  Bind(wxEVT_MENU, [this, lensId](wxCommandEvent&) { LoadImages(lensId); }, lensTypeId);
581  ++lensTypeId;
582  };
583 
584  m_alignButton = XRCCTRL(*this, "ass_align_button", SplitButton);
586  m_alignButton->Disable();
587  // add default assistant to drop down menu
588  m_alignButton->GetSplitButtonMenu()->Append(ID_ASSISTANT_MENU, _("Panorama assistant (default)"), m_alignButton->GetToolTipText());
589  Bind(wxEVT_MENU, &GLPreviewFrame::OnAlign, this, ID_ASSISTANT_MENU);
590  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
591  // provide help texts in the status bar, add the necessary event handlers
592  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
593  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
594  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_alignButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
595  );
596 
597  m_createButton = XRCCTRL(*this, "ass_create_button", SplitButton);
599  m_createButton->Disable();
600  // add default create function to drop down menu
601  m_createButton->GetSplitButtonMenu()->Append(ID_CREATEPANO_MENU, _("Stitch normal panorama (default)"), m_createButton->GetToolTipText());
602  Bind(wxEVT_MENU, &GLPreviewFrame::OnCreate, this, ID_CREATEPANO_MENU);
603  m_createButton->GetSplitButtonMenu()->AppendSeparator();
604  // provide help texts in the status bar, add the necessary event handlers
605  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
606  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
607  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_createButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
608  );
609 
610  m_ProjectionChoice = XRCCTRL(*this,"projection_choice",wxChoice);
611 
612  /* populate with all available projection types */
613  int nP = panoProjectionFormatCount();
614  for(int n=0; n < nP; n++) {
615  pano_projection_features proj;
616  if (panoProjectionFeaturesQuery(n, &proj)) {
617  wxString str2(proj.name, wxConvLocal);
618  m_ProjectionChoice->Append(wxGetTranslation(str2));
619  }
620  }
621  m_ProjectionChoice->SetSelection(2);
622 
624  // Blend mode
625  // remaining blend mode should be added after OpenGL context has been created
626  // see FillBlendMode()
627  m_differenceIndex = -1;
628  // create choice item
629  m_BlendModeChoice = XRCCTRL(*this,"blend_mode_choice",wxChoice);
630  m_BlendModeChoice->Append(_("normal"));
631  m_BlendModeChoice->SetSelection(0);
632 
633  m_DragModeChoice = XRCCTRL(*this, "drag_mode_choice", wxChoice);
635  bool individualDrag;
636  cfg->Read(wxT("/GLPreviewFrame/individualDragMode"), &individualDrag, false);
637  if(individualDrag)
638  {
639  m_DragModeChoice->SetSelection(1);
640  }
641  else
642  {
643  m_DragModeChoice->SetSelection(0);
644  };
645  // default drag mode
647 
648  // TODO implement hdr display in OpenGL, if possible?
649  // Disabled until someone can figure out HDR display in OpenGL.
650  /*
652  // LDR, HDR
653  blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")),
654  0, // not vertically strechable
655  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
656  5); // border width
657 
658  m_choices[0] = _("LDR");
659  m_choices[1] = _("HDR");
660  m_outputModeChoice = new wxChoice(this, ID_OUTPUTMODE_CHOICE,
661  wxDefaultPosition, wxDefaultSize,
662  2, m_choices);
663  m_outputModeChoice->SetSelection(0);
664  blendModeSizer->Add(m_outputModeChoice,
665  0,
666  wxALL | wxALIGN_CENTER_VERTICAL,
667  5);
668  */
669 
671  // exposure
672  m_defaultExposureBut = XRCCTRL(*this, "exposure_default_button", wxBitmapButton);
673 
674  m_exposureTextCtrl = XRCCTRL(*this, "exposure_text", wxTextCtrl);
675  m_exposureTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
676 
677  m_exposureSpinBut = XRCCTRL(*this, "exposure_spin", wxSpinButton);
678  m_exposureSpinBut->SetValue(0);
679  m_exposureSpinBut->SetMaxSize(wxSize(-1, m_exposureTextCtrl->GetSize().GetHeight()));
680 
681  m_rangeCompressionTextCtrl = XRCCTRL(*this, "range_compression_text", wxTextCtrl);
682  m_rangeCompressionTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
683 
684  m_rangeCompressionSpinBut = XRCCTRL(*this, "range_compression_spin", wxSpinButton);
685  m_rangeCompressionSpinBut->SetValue(0);
686  m_rangeCompressionSpinBut->SetMaxSize(wxSize(-1, m_rangeCompressionTextCtrl->GetSize().GetHeight()));
687 
688  m_projection_panel = XRCCTRL(*this, "projection_panel", wxPanel);
689  m_projParamSizer = new wxBoxSizer(wxHORIZONTAL);
690 
691  wxBitmapButton * resetProjButton=new wxBitmapButton(m_projection_panel, PROJ_PARAM_RESET_ID,
692  wxArtProvider::GetBitmap(wxART_REDO));
693  resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
694  m_projParamSizer->Add(resetProjButton, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
695 
696  m_projParamNamesLabel.resize(PANO_PROJECTION_MAX_PARMS);
697  m_projParamTextCtrl.resize(PANO_PROJECTION_MAX_PARMS);
698  m_projParamSlider.resize(PANO_PROJECTION_MAX_PARMS);
699 
700  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
701 
702  wxBoxSizer* paramBoxSizer = new wxBoxSizer(wxVERTICAL);
703  m_projParamNamesLabel[i] = new wxStaticText(m_projection_panel, PROJ_PARAM_NAMES_ID+i, _("param:"));
704  paramBoxSizer->Add(m_projParamNamesLabel[i],
705  0, // not vertically strechable
706  wxLEFT | wxRIGHT, // draw border all around
707  5); // border width
708  m_projParamTextCtrl[i] = new wxTextCtrl(m_projection_panel, PROJ_PARAM_VAL_ID+i, wxT("0"),
709  wxDefaultPosition, wxSize(35,-1), wxTE_PROCESS_ENTER);
710  m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
711  paramBoxSizer->Add(m_projParamTextCtrl[i],
712  0, // not vertically strechable
713  wxLEFT | wxRIGHT, // draw border all around
714  5); // border width
715 
716  m_projParamSizer->Add(paramBoxSizer);
717  m_projParamSlider[i] = new wxSlider(m_projection_panel, PROJ_PARAM_SLIDER_ID+i, 0, -90, 90);
719  1, // not vertically strechable
720  wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL , // draw border all around
721  5); // border width
722  }
723 
724  m_projection_panel->GetSizer()->Add(m_projParamSizer, 1, wxALIGN_CENTER_VERTICAL);
725 
726  // do not show projection param sizer
727  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
728 
729  // the initial size as calculated by the sizers
730  this->SetSizer( m_topsizer );
731  m_topsizer->SetSizeHints( this );
732 
733  // set the minimize icon
734 #ifdef __WXMSW__
735  wxIconBundle myIcons(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
736  SetIcons(myIcons);
737 #else
738  wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
739  SetIcon(myIcon);
740 #endif
741 
742  m_pano.addObserver(this);
743 
744  RestoreFramePosition(this, wxT("GLPreviewFrame"));
745 
746 #ifdef __WXMSW__
747  // wxFrame does have a strange background color on Windows..
748  this->SetBackgroundColour(m_GLPreview->GetBackgroundColour());
749 #endif
750 
751  m_showProjectionHints = cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"), HUGIN_SHOW_PROJECTION_HINTS) == 1;
752  m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigitsEdit"),3);
753 
754  // tell the manager to "commit" all the changes just made
755  m_mgr->Update();
756 
757  if (cfg->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0)
758  {
759 #if defined __WXMSW__ || defined __WXMAC__
760  InitPreviews();
761  Show();
762 #else
763  Show();
765 #endif
766  }
767  SetDropTarget(new PanoDropTarget(m_pano, true));
768 #if defined __WXMAC__
769  Layout();
770  Update();
771 #endif
772 }
773 
775 {
776 #ifdef __WXGTK__
777  if(loadedLayout)
778  {
779  return;
780  };
781  loadedLayout=true;
782 #endif
783  wxString OpenGLLayout=wxConfig::Get()->Read(wxT("/GLPreviewFrame/OpenGLLayout"));
784  if(!OpenGLLayout.IsEmpty())
785  {
786  m_mgr->LoadPerspective(OpenGLLayout,true);
787 #ifdef __WXGTK__
788  if(!GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked())
789  {
790  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
791  if (inf.IsOk())
792  {
793  inf.Hide();
794  }
795  m_GLOverview->SetActive(false);
796  };
797  m_mgr->Update();
798  wxShowEvent dummy;
799  dummy.SetShow(true);
800  OnShowEvent(dummy);
801 #endif
802  };
803  FillBlendChoice();
804 };
805 
807 {
808  wxConfigBase * cfg = wxConfigBase::Get();
809 
810  StoreFramePosition(this, wxT("GLPreviewFrame"));
811 
812  if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
813  cfg->Write(wxT("/GLPreviewFrame/isShown"), 1l);
814  } else {
815  cfg->Write(wxT("/GLPreviewFrame/isShown"), 0l);
816  }
817 
818  cfg->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection());
819  cfg->Write(wxT("/GLPreviewFrame/OpenGLLayout"), m_mgr->SavePerspective());
820  cfg->Write(wxT("/GLPreviewFrame/overview_hidden"), !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
821  cfg->Write(wxT("/GLPreviewFrame/showPreviewGrid"), GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
822  cfg->Write(wxT("/GLPreviewFrame/individualDragMode"), individualDragging());
823  cfg->Write(wxT("/GLPreviewFrame/guide"),m_GuideChoiceProj->GetSelection());
824 };
825 
827 {
828  DEBUG_TRACE("dtor writing config");
830 
831  // delete all of the tools. When the preview is never used we never get an
832  // OpenGL context and therefore don't create the tools.
833  if (crop_tool)
834  {
842  preview_helper->DeactivateTool(preview_control_point_tool); delete preview_control_point_tool;
846  }
857  }
865  }
866  m_exposureTextCtrl->PopEventHandler(true);
867  m_HFOVText->PopEventHandler(true);
868  m_rangeCompressionTextCtrl->PopEventHandler(true);
869  m_VFOVText->PopEventHandler(true);
870  m_ROILeftTxt->PopEventHandler(true);
871  m_ROIRightTxt->PopEventHandler(true);
872  m_ROITopTxt->PopEventHandler(true);
873  m_ROIBottomTxt->PopEventHandler(true);
874  for (int i=0; i < m_ToggleButtons.size(); i++)
875  {
876  m_ToggleButtons[i]->PopEventHandler(true);
877  m_GroupToggleButtons[i]->PopEventHandler(true);
878  }
879  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
880  {
881  m_projParamTextCtrl[i]->PopEventHandler(true);
882  };
883  m_pano.removeObserver(this);
884 
885  // deinitialize the frame manager
886  m_mgr->UnInit();
887  if (m_mgr) {
888  delete m_mgr;
889  }
891  {
892  delete m_filemenuSimple;
893  }
894  else
895  {
896  delete m_filemenuAdvanced;
897  };
898 
899  DEBUG_TRACE("dtor end");
900 }
901 
903 {
905  {
909  };
910 };
911 
916 {
917  if (m_BlendModeChoice != NULL)
918  {
919  int index=m_BlendModeChoice->GetSelection();
920  if(index==0)
921  {
922  // normal mode
923  if (preview_helper != NULL
924  && difference_tool != NULL)
925  {
927  };
928 
929  if (panosphere_overview_helper != NULL
930  && panosphere_difference_tool != NULL)
931  {
933  };
934 
935  if (plane_overview_helper != NULL
936  && plane_difference_tool != NULL)
937  {
939  };
940 
941 
942  }
943  else
944  {
945  if(index==m_differenceIndex)
946  {
947  // difference mode
948  if (preview_helper != NULL
949  && identify_tool != NULL
950  && difference_tool != NULL )
951  {
953 // preview_helper->DeactivateTool(identify_tool);
954  m_identify_togglebutton->SetValue(false);
957  };
958 
959  // difference mode
960  if (panosphere_overview_helper != NULL
962  && panosphere_difference_tool != NULL)
963  {
964 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
967  };
968 
969  // difference mode
970  if (plane_overview_helper != NULL
971  && plane_overview_identify_tool != NULL
972  && plane_difference_tool != NULL)
973  {
974 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
977  };
978 
979  }
980  else
981  {
982  DEBUG_WARN("Unknown blend mode selected");
983  };
984  }
985  }
986 }
987 
989 {
990  m_ROILeftTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().left() ));
991  m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().right() ));
992  m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().top() ));
993  m_ROIBottomTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().bottom() ));
994 
995  // display the current aspect ratio
996  if (opts.getROI().area() > 0)
997  {
998  const int commonDivisor = hugin_utils::gcd(opts.getROI().width(), opts.getROI().height());
999  wxString labelAspectRatio;
1000  if (commonDivisor > std::pow(10, hugin_utils::floori(log10f(std::max(opts.getROI().width(), opts.getROI().height()))) - 2))
1001  {
1002  labelAspectRatio = wxString::Format("%d:%d", opts.getROI().width() / commonDivisor, opts.getROI().height() / commonDivisor);
1003  }
1004  else
1005  {
1006  const float ratio = 1.0f * opts.getROI().width() / opts.getROI().height();
1007  if (ratio > 1.0f)
1008  {
1009  labelAspectRatio=wxString::Format("%.2f:1", ratio);
1010  }
1011  else
1012  {
1013  labelAspectRatio=wxString::Format("1:%.2f", 1.0f / ratio);
1014  };
1015  };
1016  XRCCTRL(*this, "crop_aspect_label", wxStaticText)->SetLabel(labelAspectRatio);
1017  };
1018 
1019 };
1020 
1022 {
1023  m_alignButton->Enable(pano.getNrOfImages()>0);
1024 
1025  if(pano.getNrOfImages()==0)
1026  {
1027  m_createButton->Disable();
1028  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("No images loaded."));
1029  }
1030  else
1031  {
1032  bool enableCreate = false;
1033  // check if images are at position 0
1034  for (size_t i = 0; i < pano.getNrOfImages(); ++i)
1035  {
1036  const HuginBase::SrcPanoImage& img = pano.getImage(i);
1037  if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
1038  {
1039  enableCreate = true;
1040  break;
1041  };
1042  };
1043  // disable create button after loading images
1044  const std::string lastCmd = PanoCommand::GlobalCmdHist::getInstance().getLastCommandName();
1045  if (lastCmd == "add images" || lastCmd == "add and distribute images")
1046  {
1047  enableCreate = false;
1048  };
1049  if (!enableCreate && pano.getNrOfImages() == 1)
1050  {
1051  // some more checks for single image projects
1053  {
1054  enableCreate = true;
1055  };
1056  if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
1057  {
1058  enableCreate = true;
1059  };
1060  if (pano.getImage(0).getProjection() == HuginBase::SrcPanoImage::EQUIRECTANGULAR)
1061  {
1062  enableCreate = true;
1063  };
1064  };
1065  m_createButton->Enable(enableCreate);
1066  }
1067 
1068  if (pano.getNrOfImages() > 1)
1069  {
1070  // in wxWidgets 2.9, format must have types that exactly match.
1071  // However std::size_t could be any unsiged integer, so we cast it to
1072  // unsigned long.int to be on the safe side.
1073  wxString alignMsg = wxString::Format(_("%lu images are connected by %lu control points.\n"), (unsigned long int) pano.getNrOfImages(), (unsigned long int) pano.getCtrlPoints().size());
1074 
1075  if (m_pano.getNrOfCtrlPoints() > 0)
1076  {
1077  // find components..
1079  const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
1080  if (comps.size() > 1)
1081  {
1082  alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
1083  }
1084  else
1085  {
1086  if (m_pano.needsOptimization())
1087  {
1088  alignMsg += _("Images or control points have changed, new alignment is needed.");
1089  }
1090  else
1091  {
1092  HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages(), MainFrame::Get()->GetOptimizeIgnoreLineCp());
1093  calcStats.run();
1094  const double max = calcStats.getResultMax();
1095  const double mean = calcStats.getResultMean();
1096 
1097  if (max != 0.0)
1098  {
1099  alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max);
1100  }
1101  }
1102  }
1103  }
1104  wxStaticText* statusCtrl = XRCCTRL(*this, "ass_status_text", wxStaticText);
1105  statusCtrl->SetLabel(alignMsg);
1106  statusCtrl->InvalidateBestSize();
1107  m_tool_notebook->GetPage(0)->Layout();
1108  Refresh();
1109  }
1110  else
1111  {
1112  if (pano.getNrOfImages() == 1)
1113  {
1114  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("One image loaded."));
1115  };
1116  };
1117 
1118  GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
1119  GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
1120 
1121  // TODO: update meaningful help text and dynamic links to relevant tabs
1122 
1123  const HuginBase::PanoramaOptions & opts = pano.getOptions();
1124 
1125  wxString projection;
1126  m_ProjectionChoice->SetSelection(opts.getProjection());
1127  m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
1128 
1129  // No HDR display yet.
1130  /*
1131  m_outputModeChoice->SetSelection(opts.outputMode);
1132  if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
1133  m_exposureTextCtrl->Hide();
1134  m_defaultExposureBut->Hide();
1135  m_decExposureBut->Hide();
1136  m_incExposureBut->Hide();
1137  } else {
1138  m_exposureTextCtrl->Show();
1139  m_defaultExposureBut->Show();
1140  m_decExposureBut->Show();
1141  m_incExposureBut->Show();
1142  }*/
1143  m_exposureTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
1144  m_rangeCompressionTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputRangeCompression, 1).c_str(), wxConvLocal));
1145 
1146  const bool activeImgs = !pano.getActiveImages().empty();
1147 
1148  // TODO: enable display of parameters and set their limits, if projection has some.
1149 
1150  int nParam = opts.m_projFeatures.numberOfParameters;
1151  bool relayout = false;
1152  // if the projection format has changed
1153  if (opts.getProjection() != m_oldProjFormat) {
1154  DEBUG_DEBUG("Projection format changed");
1155  if (nParam) {
1156  // show parameters and update labels.
1157  m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
1158  int i;
1159  for (i=0; i < nParam; i++) {
1160  const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
1161  wxString str2(pp->name, wxConvLocal);
1162  str2 = wxGetTranslation(str2);
1163  m_projParamNamesLabel[i]->SetLabel(str2);
1164  m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
1165  }
1166  for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
1167  m_projParamNamesLabel[i]->Hide();
1168  m_projParamSlider[i]->Hide();
1169  m_projParamTextCtrl[i]->Hide();
1170  }
1171  relayout = true;
1172  } else {
1173  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
1174  relayout = true;
1175  }
1176  }
1177  if (nParam) {
1178  // display new values
1179  std::vector<double> params = opts.getProjectionParameters();
1180  assert((int) params.size() == nParam);
1181  for (int i=0; i < nParam; i++) {
1182  wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
1183  m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
1184  m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
1185  }
1186  }
1187  if (relayout) {
1188  m_projection_panel->Layout();
1189  Refresh();
1190  }
1191  SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
1192  m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
1193  m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
1194  std::string val;
1195  val = hugin_utils::doubleToString(opts.getHFOV(),1);
1196  m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1197  val = hugin_utils::doubleToString(opts.getVFOV(),1);
1198  m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1199  m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
1200 
1201  m_oldProjFormat = opts.getProjection();
1202 
1203  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
1204  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
1205  UpdateRoiDisplay(opts);
1206 
1208  {
1210  };
1211  redrawPreview();
1212 }
1213 
1215 {
1216  DEBUG_TRACE("");
1217 
1218  bool dirty = false;
1219 
1220  unsigned int nrImages = pano.getNrOfImages();
1221  unsigned int nrButtons = m_ToggleButtons.size();
1222 
1223  GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
1224 
1225 // m_displayedImgs.clear();
1226 
1227  // remove items for nonexisting images
1228  for (int i=nrButtons-1; i>=(int)nrImages; i--)
1229  {
1230  m_ButtonSizer->Detach(m_ToggleButtonPanel[i]);
1231  // Image toggle buttons have a event handler on the stack which
1232  // must be removed before the buttons get destroyed.
1233  m_ToggleButtons[i]->PopEventHandler();
1234  m_GroupToggleButtons[i]->PopEventHandler();
1235  delete m_ToggleButtons[i];
1236  delete m_GroupToggleButtons[i];
1237  delete m_ToggleButtonPanel[i];
1238  m_ToggleButtons.pop_back();
1239  m_GroupToggleButtons.pop_back();
1240  m_ToggleButtonPanel.pop_back();
1241  delete toogle_button_event_handlers[i];
1242  toogle_button_event_handlers.pop_back();
1245  dirty = true;
1246  }
1247 
1248  //change overview mode to panosphere if the translation plane parameter are non zero
1250  {
1252  {
1254  m_OverviewModeChoice->SetSelection(0);
1255  //check if drag mode is mosaic, if so reset to normal
1256  if(drag_tool)
1257  {
1259  {
1260  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
1263  // adjust the layout
1264  DragChoiceLayout(m_DragModeChoice->GetSelection());
1265  };
1266  };
1267  }
1268  }
1269 
1270  // add buttons
1271  if ( nrImages >= nrButtons ) {
1272  for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
1273  if (*it >= nrButtons) {
1274  // create new item.
1275 // wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
1276  //put wxToggleButton in a wxPanel because
1277  //on Windows the background colour of wxToggleButton can't be changed
1278  wxPanel *pan = new wxPanel(m_ButtonPanel);
1279  wxBoxSizer * siz = new wxBoxSizer(wxVERTICAL);
1280  pan->SetSizer(siz);
1281  wxToggleButton * but = new wxToggleButton(pan,
1282  ID_TOGGLE_BUT + *it,
1283  wxString::Format(wxT(" %d "),*it),
1284  wxDefaultPosition, wxDefaultSize,
1285  wxBU_EXACTFIT);
1286 
1287  wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxT(""));
1288 
1289 #if defined __WXMSW__ || defined __WXMAC__
1290  //we need a border around the button to see the colored panel
1291  //because changing backgroundcolor of wxToggleButton does not work in wxMSW
1292  siz->AddSpacer(5);
1293  siz->Add(butcheck, 0, wxALIGN_CENTRE_HORIZONTAL | wxFIXED_MINSIZE, 0);
1294  siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
1295 #else
1296  siz->Add(but,0,wxALL ,0);
1297  siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
1298 #endif
1299  // for the identification tool to work, we need to find when the
1300  // mouse enters and exits the button. We use a custom event
1301  // handler, which will also toggle the images:
1302  ImageToogleButtonEventHandler * event_handler = new ImageToogleButtonEventHandler(*it, m_identify_togglebutton, &m_pano);
1303  event_handler->AddIdentifyTool(&identify_tool);
1306  toogle_button_event_handlers.push_back(event_handler);
1307  but->PushEventHandler(event_handler);
1308 
1309  ImageGroupButtonEventHandler * group_event_handler = new
1310  ImageGroupButtonEventHandler(*it, this, &m_pano);
1311  group_event_handler->AddDragTool((DragTool**) &drag_tool);
1312  group_event_handler->AddDragTool((DragTool**) &overview_drag_tool);
1313  group_event_handler->AddIdentifyTool(&identify_tool);
1314  group_event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
1315  group_event_handler->AddIdentifyTool(&plane_overview_identify_tool);
1316  toggle_group_button_event_handlers.push_back(group_event_handler);
1317  butcheck->PushEventHandler(group_event_handler);
1318  butcheck->Show(individualDragging() && m_mode==mode_drag);
1319 
1320  but->SetValue(true);
1321  m_ButtonSizer->Add(pan,
1322  0,
1323  wxLEFT | wxTOP,
1324  0);
1325  m_ToggleButtons.push_back(but);
1326  m_GroupToggleButtons.push_back(butcheck);
1327  m_ToggleButtonPanel.push_back(pan);
1328  dirty = true;
1329  }
1330  }
1331  }
1332 
1333  // update existing items
1334  HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
1335  for (unsigned i=0; i < nrImages; i++) {
1336  m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
1337  wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
1338  m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
1339  }
1340 
1341  if (dirty) {
1342  m_ButtonSizer->FitInside(m_ButtonPanel);
1343  Layout();
1344  SendSizeEvent();
1345  DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
1346  DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
1347  }
1348  if(nrImages==0)
1349  {
1351  m_tool_notebook->ChangeSelection(mode_assistant);
1352  };
1353  for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
1354  {
1355  m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
1356  };
1357  redrawPreview();
1358 }
1359 
1361 {
1362  m_GLPreview->Refresh();
1363  m_GLOverview->Refresh();
1364 }
1365 
1367 {
1368  if (preview_helper)
1369  {
1371  m_GLPreview->Redraw();
1372  };
1373 }
1374 
1375 void GLPreviewFrame::OnShowEvent(wxShowEvent& e)
1376 {
1377 
1378  DEBUG_TRACE("OnShow");
1379  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1380  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1381  if (inf.IsOk()) {
1382  if (e.IsShown()) {
1383  if (!inf.IsShown() && toggle_on ) {
1384  inf.Show();
1385  m_mgr->Update();
1386  }
1387  } else {
1388  if (inf.IsFloating() && inf.IsShown()) {
1389  DEBUG_DEBUG("hiding overview float");
1390  inf.Hide();
1391  m_mgr->Update();
1392  }
1393  }
1394  }
1395 
1396 }
1397 
1398 //the following methods are to substitude the GLViewer KeyUp and KeyDown methods
1399 //so that tools use key events that happen globally to the preview frame
1400 //however only key up event is sent, and not key down
1401 //so until this is resolved they will remain to be handled by GLViewer
1402 void GLPreviewFrame::KeyDown(wxKeyEvent& e)
1403 {
1404  if (preview_helper) {
1405  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1406  }
1407  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1409  if (plane_overview_helper) {
1410  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1411  }
1414  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1415  }
1416  }
1417 
1418  }
1419  e.Skip();
1420 }
1421 
1422 void GLPreviewFrame::KeyUp(wxKeyEvent& e)
1423 {
1424  if (preview_helper) {
1425  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1426  }
1427  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1429  if (plane_overview_helper) {
1430  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1431  }
1432  }
1435  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1436  }
1437  }
1438 
1439  }
1440  e.Skip();
1441 }
1442 
1443 
1444 
1445 void GLPreviewFrame::OnOverviewToggle(wxCommandEvent& e)
1446 {
1447  DEBUG_TRACE("overview toggle");
1448  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1449  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1450  if (inf.IsOk()) {
1451  if (inf.IsShown() && !toggle_on) {
1452  inf.Hide();
1453  m_GLOverview->SetActive(false);
1454  m_mgr->Update();
1455  } else if (!(inf.IsShown() && toggle_on)) {
1456  inf.Show();
1457 #if defined __WXMSW__ || defined __WXMAC__
1458  m_GLOverview->SetActive(true);
1459  m_mgr->Update();
1460 #else
1461  m_mgr->Update();
1462  m_GLOverview->SetActive(true);
1463 #endif
1464  }
1465  }
1466 }
1467 
1468 void GLPreviewFrame::OnSwitchPreviewGrid(wxCommandEvent & e)
1469 {
1470  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
1471  {
1474  }
1475  else
1476  {
1479  }
1480  m_GLPreview->Refresh();
1481  m_GLOverview->Refresh();
1482 }
1483 
1484 void GLPreviewFrame::OnClose(wxCloseEvent& event)
1485 {
1486  DEBUG_TRACE("OnClose")
1487  // do not close, just hide if we're not forced
1488  if(m_guiLevel==GUI_SIMPLE)
1489  {
1490  if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
1491  {
1492  if (event.CanVeto())
1493  {
1494  event.Veto();
1495  return;
1496  };
1497  };
1498  MainFrame::Get()->Close(true);
1499  }
1500  else
1501  {
1502  if (event.CanVeto())
1503  {
1504  event.Veto();
1505  Hide();
1506  DEBUG_DEBUG("hiding");
1507  }
1508  else
1509  {
1510  DEBUG_DEBUG("closing");
1511  this->Destroy();
1512  }
1513  };
1514 }
1515 
1516 #if 0
1517 // need to add the wxChoice somewhere
1518 void PreviewFrame::OnProjectionChanged()
1519 {
1520  PanoramaOptions opt = m_pano.getOptions();
1521  int lt = m_ProjectionChoice->GetSelection();
1522  wxString Ip;
1523  switch ( lt ) {
1524  case PanoramaOptions::RECTILINEAR: Ip = _("Rectilinear"); break;
1525  case PanoramaOptions::CYLINDRICAL: Ip = _("Cylindrical"); break;
1526  case PanoramaOptions::EQUIRECTANGULAR: Ip = _("Equirectangular"); break;
1527  }
1528  opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
1530  new PanoCommand::SetPanoOptionsCmd( pano, opt )
1531  );
1532  DEBUG_DEBUG ("Projection changed: " << lt << ":" << Ip )
1533 
1534 
1535 }
1536 #endif
1537 
1539 {
1540  if (m_pano.getActiveImages().empty()) return;
1541 
1542  // reset zoom so that full pano is visible
1543  ResetPreviewZoom();
1546  );
1547 }
1548 
1549 void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
1550 {
1551  if (m_pano.getNrOfImages() == 0) return;
1552 
1555  );
1556 }
1557 
1558 void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
1559 {
1560  if (m_pano.getActiveImages().empty()) return;
1561 
1562  DEBUG_TRACE("");
1565  fitPano.run();
1566  opt.setHFOV(fitPano.getResultHorizontalFOV());
1568 
1569  // reset zoom so that full pano is visible
1570  ResetPreviewZoom();
1571 
1574  );
1575 
1576  DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
1577 }
1578 
1579 void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
1580 {
1581  if (m_pano.getNrOfImages() == 0) return;
1582 
1583  HuginBase::UIntSet displayedImgs;
1585  {
1586  fill_set(displayedImgs, 0, m_pano.getNrOfImages() - 1);
1587  }
1588  else
1589  {
1591  {
1592  displayedImgs = m_pano.getActiveImages();
1593  };
1594  std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
1595  for (size_t i = 0; i < stackedImg.size(); ++i)
1596  {
1597  switch (m_selectAllMode)
1598  {
1600  displayedImgs.insert(*(stackedImg[i].rbegin()));
1601  break;
1602  case SELECT_DARKEST_IMAGES:
1603  displayedImgs.insert(*(stackedImg[i].begin()));
1604  break;
1605  case SELECT_MEDIAN_IMAGES:
1606  default:
1607  displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
1608  break;
1609  };
1610  };
1611  };
1613  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1614  );
1615 }
1616 
1617 void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
1618 {
1619  if (m_pano.getNrOfImages() == 0) return;
1620 
1622  for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
1623  m_ToggleButtons[i]->SetValue(false);
1624  }
1625  HuginBase::UIntSet displayedImgs;
1627  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1628  );
1629 }
1630 
1631 void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
1632 {
1633  if (m_pano.getNrOfImages() == 0) return;
1634 
1635  wxString text;
1636  double y;
1637  double p;
1638  double r;
1639  double x;
1640  double z;
1641 
1642  int index = m_DragModeChoice->GetSelection();
1643  switch (index) {
1644  case 0: //normal
1645  case 1: //normal, individual
1646  //@TODO limit numeric transform to selected images
1647  text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
1648  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1649  {
1650  wxBell();
1651  wxMessageBox(_("Yaw value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1652  return;
1653  }
1654  text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
1655  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
1656  {
1657  wxBell();
1658  wxMessageBox(_("Pitch value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1659  return;
1660  }
1661  text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
1662  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
1663  {
1664  wxBell();
1665  wxMessageBox(_("Roll value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1666  return;
1667  }
1669  new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
1670  );
1671  break;
1672  case 2: //mosaic
1673  case 3: //mosaic, individual
1674  //@TODO limit numeric transform to selected images
1675  text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
1676  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
1677  {
1678  wxBell();
1679  wxMessageBox(_("X value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1680  return;
1681  }
1682  text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
1683  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1684  {
1685  wxBell();
1686  wxMessageBox(_("Y value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1687  return;
1688  }
1689  text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
1690  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
1691  {
1692  wxBell();
1693  wxMessageBox(_("Z value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1694  return;
1695  }
1698  );
1699  break;
1700  }
1701 }
1702 
1703 void GLPreviewFrame::OnExposureChanged(wxCommandEvent & e)
1704 {
1706  // exposure
1707  wxString text = m_exposureTextCtrl->GetValue();
1708  DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
1709  double p = 0;
1710  if (text != wxT("")) {
1711  if (!hugin_utils::str2double(text, p)) {
1712  wxLogError(_("Value must be numeric."));
1713  return;
1714  }
1715  }
1716  opts.outputExposureValue = p;
1719  );
1720 }
1721 
1723 {
1728  );
1729 }
1730 
1732 {
1737  );
1738 }
1739 
1741 {
1743  // range compression
1744  const wxString text = m_rangeCompressionTextCtrl->GetValue();
1745  if (!text.IsEmpty())
1746  {
1747  double p = 0;
1748  if (!hugin_utils::str2double(text, p))
1749  {
1750  wxLogError(_("Value must be numeric."));
1751  return;
1752  };
1753  if (p < 0 || p>20)
1754  {
1755  wxLogError(_("Value for range compression is outside of valid range."));
1756  return;
1757  };
1758  if (p != opts.outputRangeCompression)
1759  {
1760  opts.outputRangeCompression = p;
1763  );
1764  };
1765  };
1766 }
1767 
1768 
1770 {
1772  int nParam = opts.m_projFeatures.numberOfParameters;
1773  std::vector<double> para = opts.getProjectionParameters();
1774  for (int i = 0; i < nParam; i++) {
1775  if (e.GetEventObject() == m_projParamTextCtrl[i]) {
1776  wxString text = m_projParamTextCtrl[i]->GetValue();
1777  DEBUG_INFO ("param " << i << ": = " << text.mb_str(wxConvLocal) );
1778  double p = 0;
1779  if (text != wxT("")) {
1780  if (!hugin_utils::str2double(text, p)) {
1781  wxLogError(_("Value must be numeric."));
1782  return;
1783  }
1784  }
1785  para[i] = p;
1786  }
1787  }
1788  opts.setProjectionParameters(para);
1791  );
1792 }
1793 
1795 {
1800  );
1801 };
1802 
1803 void GLPreviewFrame::OnChangeFOV(wxScrollEvent & e)
1804 {
1805  DEBUG_TRACE("");
1806 
1808 
1809  if (e.GetEventObject() == m_HFOVSlider) {
1810  DEBUG_DEBUG("HFOV changed (slider): " << e.GetInt() << " == " << m_HFOVSlider->GetValue());
1811  opt.setHFOV(e.GetInt());
1812  } else if (e.GetEventObject() == m_VFOVSlider) {
1813  DEBUG_DEBUG("VFOV changed (slider): " << e.GetInt());
1814  opt.setVFOV(e.GetInt());
1815  } else if (e.GetEventObject() == XRCCTRL(*this,"layout_scale_slider",wxSlider)) {
1816  DEBUG_DEBUG("Layout scale changed (slider): " << e.GetInt());
1818  } else {
1819  int nParam = opt.m_projFeatures.numberOfParameters;
1820  std::vector<double> para = opt.getProjectionParameters();
1821  for (int i = 0; i < nParam; i++) {
1822  if (e.GetEventObject() == m_projParamSlider[i]) {
1823  // update
1824  para[i] = e.GetInt();
1825  break;
1826  }
1827  }
1828  opt.setProjectionParameters(para);
1829  opt.setHFOV(m_HFOVSlider->GetValue());
1830  opt.setVFOV(m_VFOVSlider->GetValue());
1831  }
1832 
1835  );
1836 }
1837 
1838 void GLPreviewFrame::OnTrackChangeFOV(wxScrollEvent & e)
1839 {
1840  DEBUG_TRACE("");
1841  DEBUG_TRACE("fov change " << e.GetInt());
1843 
1844  if (e.GetEventObject() == m_HFOVSlider) {
1845  opt.setHFOV(e.GetInt());
1846  } else if (e.GetEventObject() == m_VFOVSlider) {
1847  opt.setVFOV(e.GetInt());
1848  } else {
1849  int nParam = opt.m_projFeatures.numberOfParameters;
1850  std::vector<double> para = opt.getProjectionParameters();
1851  for (int i = 0; i < nParam; i++) {
1852  if (e.GetEventObject() == m_projParamSlider[i]) {
1853  // update
1854  para[i] = e.GetInt();
1855  m_projParamTextCtrl[i]->ChangeValue(wxString::Format("%d", e.GetInt()));
1856  break;
1857  }
1858  }
1859  opt.setProjectionParameters(para);
1860  }
1861  // we only actually update the panorama fully when the mouse is released.
1862  // As we are dragging it we don't want to create undo events, but we would
1863  // like to update the display, so we change the GLViewer's ViewState and
1864  // request a redraw.
1866  m_GLPreview->Refresh();
1867 }
1868 
1869 void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
1870 {
1871  if (e.GetEventObject() == m_BlendModeChoice)
1872  {
1873  updateBlendMode();
1874  }
1875  else
1876  {
1877  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
1878  }
1879 }
1880 
1881 void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
1882 {
1883  if (drag_tool)
1884  {
1886  int index = m_DragModeChoice->GetSelection();
1887  switch (index) {
1888  case 0: //normal
1889  case 1:
1890  newDragMode=DragTool::drag_mode_normal;
1891  break;
1892  case 2: //mosaic
1893  case 3:
1894  newDragMode=DragTool::drag_mode_mosaic;
1895  break;
1896  }
1897  if(newDragMode==DragTool::drag_mode_mosaic)
1898  {
1900  {
1901  if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
1902 #ifdef __WXMSW__
1903  _("Hugin"),
1904 #else
1905  wxEmptyString,
1906 #endif
1907  wxYES_NO | wxICON_QUESTION, this) == wxYES)
1908  {
1910  }
1911  else
1912  {
1913  m_DragModeChoice->SetSelection(index-2);
1914  return;
1915  };
1916  };
1917  //switch overview mode to plane
1918  UpdateOverviewMode(1);
1919  m_OverviewModeChoice->SetSelection(1);
1920  }
1921  else
1922  {
1923  //new mode is normal
1924  //set overview back to panosphere mode
1925  UpdateOverviewMode(0);
1926  m_OverviewModeChoice->SetSelection(0);
1929  };
1930  //update drag mode
1931  drag_tool->setDragMode(newDragMode);
1933  // adjust the layout
1934  DragChoiceLayout(index);
1935  };
1936 };
1937 
1939 {
1940  size_t nr = m_pano.getNrOfImages();
1941  for (size_t i = 0 ; i < nr; i++)
1942  {
1943  if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
1944  m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
1945  {
1946  return true;
1947  };
1948  }
1949  return false;
1950 };
1951 
1953 {
1954  HuginBase::UIntSet imgs;
1956  size_t nr = newPan.getNrOfImages();
1957  for (size_t i = 0 ; i < nr ; i++)
1958  {
1959  HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
1960  img.setTranslationPlaneYaw(0);
1961  img.setTranslationPlanePitch(0);
1962  newPan.setSrcImage(i,img);
1963  imgs.insert(i);
1964  }
1967  );
1968 };
1969 
1971 {
1973  if (newMode == 1)
1974  {
1975  newOverviewMode = GLOverview::PANOSPHERE_INSIDE;
1976  }
1977  else
1978  {
1979  if (newMode == 2)
1980  {
1981  newOverviewMode = GLOverview::PLANE;
1982  };
1983  };
1984  if(m_GLOverview->GetMode()==newOverviewMode)
1985  {
1986  return true;
1987  };
1988  if (newOverviewMode == GLOverview::PLANE)
1989  {
1991  {
1993  return true;
1994  }
1995  else
1996  {
1997  if(wxMessageBox(_("The mosaic/plane mode works only correct for a remapping plane of yaw=0 and pitch=0.\nBut your project has non-zero Tpy and Tpp parameters.\nShould the Tpy and Tpp parameters reset to zero?"),
1998 #ifdef __WXMSW__
1999  _("Hugin"),
2000 #else
2001  wxEmptyString,
2002 #endif
2003  wxYES_NO | wxICON_QUESTION, this) == wxYES)
2004  {
2007  return true;
2008  }
2009  else
2010  {
2011  return false;
2012  };
2013  };
2014  }
2015  else
2016  {
2017  m_GLOverview->SetMode(newOverviewMode);
2018  return true;
2019  }
2020 };
2021 
2022 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
2023 {
2024  if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
2025  {
2028  //set drag mode to normal if new mode is panosphere mode
2030  {
2031  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
2032  OnDragChoice(e);
2033  };
2034  }
2035  else
2036  {
2037  //change mode was not successful or canceled by user, set mode choice back
2038  switch (m_GLOverview->GetMode())
2039  {
2041  m_OverviewModeChoice->SetSelection(0);
2042  break;
2044  m_OverviewModeChoice->SetSelection(1);
2045  break;
2046  case GLOverview::PLANE:
2047  m_OverviewModeChoice->SetSelection(2);
2048  break;
2049  };
2050  };
2051 };
2052 
2054 {
2055  // visibility of controls based on selected drag mode
2056  bool normalMode=index==0 || index==1;
2057  XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
2058  XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
2059  XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
2060  XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
2061  XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
2062  XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
2063  XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
2064  XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
2065  XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
2066  XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
2067  XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
2068  XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
2069  // redraw layout to compress empty space
2070  XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
2071 }
2072 
2073 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
2074 {
2075  if (m_pano.getActiveImages().size() > 0) {
2080  );
2081  }
2082 }
2083 
2084 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
2085 {
2087  opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
2090  );
2091 }
2092 
2093 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
2094 {
2096  opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
2099  );
2100 }
2101 
2102 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
2103 {
2104  if (e.GetEventObject() == m_ProjectionChoice) {
2106  int lt = m_ProjectionChoice->GetSelection();
2107  wxString Ip;
2111  );
2112  DEBUG_DEBUG ("Projection changed: " << lt);
2113  m_projection_panel->Layout();
2114  Refresh();
2115  } else {
2116  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2117  }
2118 }
2119 
2120 /* We don't have an OpenGL hdr display yet
2121 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
2122 {
2123  if (e.GetEventObject() == m_outputModeChoice) {
2124  PanoramaOptions opt = m_pano.getOptions();
2125  int lt = m_outputModeChoice->GetSelection();
2126  wxString Ip;
2127  opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
2128  PanoCommand::GlobalCmdHist::getInstance().addCommand(
2129  new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
2130  );
2131 
2132  } else {
2133  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2134  }
2135 }
2136 */
2137 
2138 void GLPreviewFrame::SetStatusMessage(wxString message)
2139 {
2140  SetStatusText(message, 0);
2141 }
2142 
2143 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
2144 {
2145  m_GLPreview->SetPhotometricCorrect(e.IsChecked());
2146 }
2147 
2149 {
2150  // create the tool objects.
2151  // we delay this until we have an OpenGL context so that they are free to
2152  // create texture objects and display lists before they are used.
2153  preview_helper = preview_helper_in;
2164  preview_control_point_tool = new PreviewControlPointTool(preview_helper);
2166 
2168  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2169  {
2171  };
2174 
2175  // activate tools that are always active.
2177  // update the blend mode which activates some tools
2178  updateBlendMode();
2180  // update toolbar
2182 }
2183 
2185 {
2186  panosphere_overview_helper = panosphere_overview_helper_in;
2192 
2195 
2197  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2198  {
2200  }
2201 
2202 
2206 
2209 
2210 
2211 
2212 }
2213 
2215 {
2216  plane_overview_helper = plane_overview_helper_in;
2219 
2223 
2226 
2229 
2230 }
2231 
2232 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
2233 {
2234  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2235  if (e.IsChecked())
2236  {
2237  m_BlendModeChoice->SetSelection(0);
2244 // TurnOffTools(preview_helper->ActivateTool(identify_tool));
2245 // TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
2246 // TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
2247  } else {
2248  identify_tool->setConstantOn(false);
2251 // preview_helper->DeactivateTool(identify_tool);
2252 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2253 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2255  }
2256  m_GLPreview->Refresh();
2257  m_GLOverview->Refresh();
2258 }
2259 
2260 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
2261 {
2262  if (!m_editCP_togglebutton->GetValue())
2263  {
2264  //process event only if edit cp tool is disabled
2265  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2266  if (e.IsChecked())
2267  {
2268  TurnOffTools(preview_helper->ActivateTool(preview_control_point_tool));
2271  }
2272  else {
2273  preview_helper->DeactivateTool(preview_control_point_tool);
2276  }
2277  m_GLPreview->Refresh();
2278  m_GLOverview->Refresh();
2279  };
2280 }
2281 
2282 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
2283 {
2284  std::set<Tool*>::iterator i;
2285  for (i = tools.begin(); i != tools.end(); ++i)
2286  {
2287  if (*i == crop_tool)
2288  {
2289  // cover up the guidelines
2290  m_GLPreview->Refresh();
2291  } else if (*i == drag_tool)
2292  {
2293  // cover up its boxes
2294  m_GLPreview->Refresh();
2295  } else if (*i == identify_tool)
2296  {
2297  // disabled the identify tool, toggle its button off.
2298  m_identify_togglebutton->SetValue(false);
2299  // cover up its indicators and restore normal button colours.
2300  m_GLPreview->Refresh();
2301  m_GLOverview->Refresh();
2303  } else if (*i == preview_control_point_tool)
2304  {
2305  // disabled the control point tool.
2306  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2307  // cover up the control point lines.
2308  m_GLPreview->Refresh();
2309  m_GLOverview->Refresh();
2310  }
2311  }
2312 }
2313 
2314 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
2315  unsigned char red,
2316  unsigned char green,
2317  unsigned char blue)
2318 {
2319  // 0, 0, 0 indicates we want to go back to the system colour.
2320  // TODO: Maybe we should test this better on different themes.
2321 #if defined __WXMSW__ || defined __WXMAC__
2322  if (red || green || blue)
2323  {
2324  // the identify tool wants us to highlight an image button in the given
2325  // colour, to match up with the display in the preview.
2326  // on windows change the color of the surhugin_utils::rounding wxPanel
2327  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2328  }
2329  else
2330  {
2331  // return to the normal colour
2332  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(m_ToggleButtonPanel[image_nr]->GetParent()->GetBackgroundColour());
2333  }
2334  m_ToggleButtonPanel[image_nr]->Refresh();
2335 #else
2336  if (red || green || blue)
2337  {
2338  // change the color of the wxToggleButton
2339  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
2340  m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2341  // black should be visible on the button's vibrant colours.
2342  m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
2343  }
2344  else
2345  {
2346  // return to the normal colour
2347  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2348  m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
2349  m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
2350  };
2351  m_ToggleButtons[image_nr]->Refresh();
2352 #endif
2353 }
2354 
2356 {
2357  // when we turn off the identification tool, any buttons that were coloured
2358  // to match the image in the preview should be given back the system themed
2359  // colours.
2360  unsigned int nr_images = m_pano.getNrOfImages();
2361  for (unsigned image = 0; image < nr_images; image++)
2362  {
2363 #if defined __WXMSW__ || defined __WXMAC__
2364  m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
2365  m_ToggleButtonPanel[image]->Refresh();
2366 #else
2367  m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2368  m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
2369  m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
2370  m_ToggleButtons[image]->Refresh();
2371 #endif
2372  }
2373 }
2374 
2375 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
2376 {
2377  // blank status text as it refers to an old tool.
2378  SetStatusText(wxT(""), 0);
2379  if (e.IsChecked())
2380  {
2381  // deactivate delete cp tool if active
2383  m_editCP_togglebutton->SetValue(false);
2385  }
2386  else
2387  {
2389  };
2390  m_GLPreview->Refresh();
2391 };
2392 
2393 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
2394 {
2396  new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
2397  );
2398  //now toggle button and deactivate tool
2399  m_colorpicker_togglebutton->SetValue(false);
2400  //direct deactivation of tool does not work because this function is called by the tool itself
2401  //so we are send an event to deactivate the tool
2402  wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
2403  e.SetInt(0);
2404  GetEventHandler()->AddPendingEvent(e);
2405 };
2406 
2407 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
2408 {
2409  // blank status text as it refers to an old tool.
2410  SetStatusText(wxT(""), 0);
2411  if (e.IsChecked())
2412  {
2413  // deactivate color picker tool
2415  m_colorpicker_togglebutton->SetValue(false);
2416  // show automatically all cp
2417  preview_helper->ActivateTool(preview_control_point_tool);
2419  }
2420  else
2421  {
2422  if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2423  {
2424  preview_helper->DeactivateTool(preview_control_point_tool);
2425  };
2427  };
2428  m_GLPreview->Refresh();
2429 };
2430 
2432  unsigned int image_number_in,
2433  wxToggleButton* identify_button_in,
2434  HuginBase::Panorama * m_pano_in)
2435 {
2436  image_number = image_number_in;
2437  m_identify_button = identify_button_in;
2438  m_pano = m_pano_in;
2439 }
2440 
2442 {
2443  // When using the identify tool, we want to identify image locations when
2444  // the user moves the mouse over the image buttons, but only if the image
2445  // is being shown.
2446  if (
2447  m_identify_button->GetValue() &&
2449  {
2450  std::vector<PreviewIdentifyTool**>::iterator it;
2451  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2452  (*(*it))->ShowImageNumber(image_number);
2453  }
2454  }
2455  e.Skip();
2456 }
2457 
2459 {
2460  // if the mouse left one of the image toggle buttons with the identification
2461  // tool active, we should stop showing the image indicator for that button.
2462  if (
2463  m_identify_button->GetValue() &&
2465  {
2466  std::vector<PreviewIdentifyTool**>::iterator it;
2467  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2468  (*(*it))->StopShowingImages();
2469  }
2470  }
2471  e.Skip();
2472 }
2473 
2475 {
2476  // the user is turning on or off an image using its button. We want to turn
2477  // the indicators on and off if appropriate correctly to. We use OnEnter
2478  // and OnLeave for the indicators, but these only work when the image is
2479  // showing, so we are carefull of the order:
2480  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
2481  wxMouseEvent null_event;
2482  if (e.IsChecked()) {
2483  activeImages.insert(image_number);
2485  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2486  );
2487  OnEnter(null_event);
2488  } else {
2489  OnLeave(null_event);
2490  activeImages.erase(image_number);
2492  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2493  );
2494  }
2495 }
2496 
2498  identify_tools.push_back(identify_tool_in);
2499 }
2500 
2501 ImageGroupButtonEventHandler::ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame* frame_in, HuginBase::Panorama* m_pano)
2502  : image_number(image_number), frame(frame_in), m_pano(m_pano) {}
2503 
2505  identify_tools.push_back(identify_tool_in);
2506 }
2507 
2508 
2510 {
2511  //mark the image
2512  if (m_pano->getActiveImages().count(image_number))
2513  {
2514  std::vector<PreviewIdentifyTool**>::iterator it;
2515  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2516  (*(*it))->ShowImageNumber(image_number);
2517  }
2518  }
2519  e.Skip();
2520 }
2521 
2523 {
2524  //unmark the image
2525  if (m_pano->getActiveImages().count(image_number))
2526  {
2527  std::vector<PreviewIdentifyTool**>::iterator it;
2528  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2529  (*(*it))->StopShowingImages();
2530  }
2531  }
2532  e.Skip();
2533 }
2534 
2536 {
2537  wxMouseEvent null_event;
2538  if (e.IsChecked()) {
2540  OnEnter(null_event);
2541  } else {
2542  OnLeave(null_event);
2544  }
2545 }
2546 
2548  drag_tools.push_back(drag_tool_in);
2549 }
2550 
2552 {
2553  return m_DragModeChoice->GetSelection()==1 ||
2554  m_DragModeChoice->GetSelection()==3;
2555 }
2556 
2557 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
2558  if (imageDragGroup.count(image_nr) == 0) {
2559  this->AddImageToDragGroup(image_nr, update_check_box);
2560  } else {
2561  this->RemoveImageFromDragGroup(image_nr, update_check_box);
2562  }
2563 }
2564 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
2565  imageDragGroup.erase(image_nr);
2566  if (update_check_box) {
2567  m_GroupToggleButtons[image_nr]->SetValue(false);
2568  }
2569 }
2570 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
2571  imageDragGroup.insert(image_nr);
2572  if (update_check_box) {
2573  m_GroupToggleButtons[image_nr]->SetValue(true);
2574  }
2575 }
2576 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
2577  imageDragGroup.swap(imageDragGroup_in);
2578  std::vector<wxCheckBox*>::iterator it;
2579  unsigned int nr = 0;
2580  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2581  (*it)->SetValue(imageDragGroup.count(nr++)>0);
2582  }
2583 }
2585  return imageDragGroup;
2586 }
2587 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
2588  imageDragGroup.clear();
2589  std::vector<wxCheckBox*>::iterator it;
2590  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2591  (*it)->SetValue(false);
2592  }
2593 }
2594 
2596 {
2597  std::vector<wxCheckBox*>::iterator it;
2598  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
2599  {
2600  (*it)->Show(isShown);
2601  }
2602  Layout();
2603 };
2604 
2607 {
2609  m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
2610  // update size
2611  m_BlendModeChoice->InvalidateBestSize();
2612  m_BlendModeChoice->GetParent()->Layout();
2613  Refresh();
2614  // get blend mode last state
2615  unsigned int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l);
2616  // limit old state to max available states
2617  if (oldMode >= m_BlendModeChoice->GetCount())
2618  {
2619  oldMode = 0;
2620  }
2621  m_BlendModeChoice->SetSelection(oldMode);
2622  updateBlendMode();
2623 };
2624 
2625 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
2626 {
2627  DEBUG_INFO("Dirty ROI Calc\n");
2628  if (m_pano.getActiveImages().empty())
2629  {
2630  return;
2631  };
2632 
2633  vigra::Rect2D newROI;
2634  {
2635  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2636  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2637  cropPano.run();
2638  if (cropPano.hasRunSuccessfully())
2639  {
2640  newROI = cropPano.getResultOptimalROI();
2641  };
2642  };
2643 
2644  //set the ROI - fail if the right/bottom is zero, meaning all zero
2645  if(!newROI.isEmpty())
2646  {
2648  opt.setROI(newROI);
2651  );
2652  }
2653 }
2654 
2655 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
2656 {
2657  DEBUG_INFO("Dirty ROI Calc\n");
2658  if (m_pano.getActiveImages().empty())
2659  {
2660  return;
2661  };
2662 
2663  vigra::Rect2D newROI;
2664  {
2665  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2666  HuginBase::UIntSet activeImages = m_pano.getActiveImages();
2667  std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
2668  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2669  //only use hdr autocrop for projects with stacks
2670  //otherwise fall back to "normal" autocrop
2671  if (stackImgs.size()<activeImages.size())
2672  {
2673  cropPano.setStacks(stackImgs);
2674  }
2675  cropPano.run();
2676  if (cropPano.hasRunSuccessfully())
2677  {
2678  newROI = cropPano.getResultOptimalROI();
2679  };
2680  };
2681 
2682  //set the ROI - fail if the right/bottom is zero, meaning all zero
2683  if(!newROI.isEmpty())
2684  {
2686  opt.setROI(newROI);
2689  );
2690  }
2691 }
2692 
2693 void GLPreviewFrame::OnAutocropOutside(wxCommandEvent& e)
2694 {
2695  DEBUG_INFO("Dirty ROI Calc\n");
2696  if (m_pano.getActiveImages().empty())
2697  {
2698  return;
2699  };
2700 
2701  vigra::Rect2D newROI;
2702  {
2703  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2704  HuginBase::CalculateOptimalROIOutside cropPano(m_pano, &progress);
2705  cropPano.run();
2706  if (cropPano.hasRunSuccessfully())
2707  {
2708  newROI = cropPano.getResultOptimalROI();
2709  };
2710  };
2711 
2712  //set the ROI - fail if the right/bottom is zero, meaning all zero
2713  if (!newROI.isEmpty())
2714  {
2716  opt.setROI(newROI);
2719  );
2720  }
2721 }
2722 
2723 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
2724 {
2725  ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
2726 };
2727 
2728 void GLPreviewFrame::SetMode(int newMode)
2729 {
2730  if(m_mode==newMode)
2731  return;
2732  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2733  switch(m_mode)
2734  {
2735  case mode_assistant:
2736  case mode_preview:
2737  // switch off identify and show cp tool
2738  identify_tool->setConstantOn(false);
2742  m_colorpicker_togglebutton->SetValue(false);
2743 // preview_helper->DeactivateTool(identify_tool);
2744 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2745 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2747  m_editCP_togglebutton->SetValue(false);
2748 
2750  m_identify_togglebutton->SetValue(false);
2751  preview_helper->DeactivateTool(preview_control_point_tool);
2754  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2755  break;
2756  case mode_layout:
2757  // disable layout mode.
2761  // reactivate identify and camera tool when leaving layout mode
2766  m_GLPreview->SetLayoutMode(false);
2767  m_GLOverview->SetLayoutMode(false);
2768  // Switch the panorama mask back on.
2770  //restore blend mode
2772  updateBlendMode();
2773  break;
2774  case mode_projection:
2776  break;
2777  case mode_drag:
2781  if (individualDragging()) {
2782  std::vector<wxCheckBox*>::iterator it;
2783  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2784  (*it)->Show(false);
2785  }
2786  }
2787  break;
2788  case mode_crop:
2792  break;
2793  };
2794  m_mode=newMode;
2795  wxScrollEvent dummy;
2796  switch(m_mode)
2797  {
2798  case mode_assistant:
2799  case mode_preview:
2800  break;
2801  case mode_layout:
2802  //save blend mode setting, set to normal for layout mode
2803  non_layout_blend_mode=m_BlendModeChoice->GetSelection();
2804  m_BlendModeChoice->SetSelection(0);
2805  updateBlendMode();
2806  // turn off things not used in layout mode.
2809  // deactivate identify tool in layout mode
2813  m_GLPreview->SetLayoutMode(true);
2814  m_GLOverview->SetLayoutMode(true);
2818  // we need to update the meshes after switch to layout mode
2819  // otherwise the following update of scale has no meshes to scale
2820  m_GLPreview->Update();
2821  m_GLOverview->Update();
2822  OnLayoutScaleChange(dummy);
2823  break;
2824  case mode_projection:
2826  break;
2827  case mode_drag:
2831  if (individualDragging()) {
2832  std::vector<wxCheckBox*>::iterator it;
2833  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2834  (*it)->Show(true);
2835  }
2836  }
2837  break;
2838  case mode_crop:
2842  break;
2843  };
2844  //enable group checkboxes only for drag mode tab
2846  m_GLPreview->Refresh();
2847 };
2848 
2849 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
2850 {
2851  if(m_mode!=-1)
2852  SetMode(e.GetSelection());
2853 };
2854 
2855 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
2856 {
2857  if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
2858  {
2859  wxBell();
2860  e.Veto();
2861  };
2862 };
2863 
2864 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
2865 {
2867  long left, right, top, bottom;
2868  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
2869  wxLogError(_("Top needs to be an integer bigger than 0"));
2870  return;
2871  }
2872  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
2873  wxLogError(_("left needs to be an integer bigger than 0"));
2874  return;
2875  }
2876  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
2877  wxLogError(_("right needs to be an integer bigger than 0"));
2878  return;
2879  }
2880  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
2881  wxLogError(_("bottom needs to be an integer bigger than 0"));
2882  return;
2883  }
2884  opt.setROI(vigra::Rect2D(left, top, right, bottom));
2885  // make sure that left is really to the left of right
2886  if(opt.getROI().width()<1) {
2887  wxLogError(_("left boundary must be smaller than right"));
2889  return;
2890  }
2891  // make sure that top is really higher than bottom
2892  if(opt.getROI().height()<1) {
2893  wxLogError(_("top boundary must be smaller than bottom"));
2895  return;
2896  }
2897 
2900  );
2901 };
2902 
2903 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
2904 {
2906  opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
2908 };
2909 
2910 void GLPreviewFrame::OnSetCropAspect(wxCommandEvent& e)
2911 {
2912  // ask user for a setting
2913  SelectAspectRatioDialog dlg(this);
2914  if (dlg.ShowModal() == wxID_OK)
2915  {
2917  const double aspectRatio = dlg.GetSelectedAspectRatio();
2918  // calculate the new ROI, move crop if necessary
2919  int left = opt.getROI().left();
2920  int top = opt.getROI().top();
2921  int width = opt.getROI().width();
2922  int height = opt.getROI().height();
2923  const int newHeight = 1.0 * width / aspectRatio;
2924  if (newHeight > height)
2925  {
2926  const int newWidth = 1.0 * height * aspectRatio;
2927  left = left + (width - newWidth) / 2.0;
2928  width = newWidth;
2929  }
2930  else
2931  {
2932  top = top + (height - newHeight) / 2.0;
2933  height = newHeight;
2934  };
2935  // finally set new crop
2936  opt.setROI(vigra::Rect2D(left, top, left + width, top + height));
2938  };
2939 }
2940 
2941 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
2942 {
2944 
2945 
2946  wxString text = m_HFOVText->GetValue();
2947  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
2948  if (text == wxT("")) {
2949  return;
2950  }
2951 
2952  double hfov;
2953  if (!hugin_utils::str2double(text, hfov)) {
2954  wxLogError(_("Value must be numeric."));
2955  return;
2956  }
2957 
2958  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
2959  wxLogError(wxString::Format(
2960  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
2961  opt.getMaxHFOV()));
2962  hfov=opt.getMaxHFOV();
2963  }
2964  opt.setHFOV(hfov);
2965  // recalculate panorama height...
2968  );
2969 
2970  DEBUG_INFO ( "new hfov: " << hfov )
2971 };
2972 
2973 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
2974 {
2976 
2977  wxString text = m_VFOVText->GetValue();
2978  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
2979  if (text == wxT("")) {
2980  return;
2981  }
2982 
2983  double vfov;
2984  if (!hugin_utils::str2double(text, vfov)) {
2985  wxLogError(_("Value must be numeric."));
2986  return;
2987  }
2988 
2989  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
2990  wxLogError(wxString::Format(
2991  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
2992  opt.getMaxVFOV()));
2993  vfov = opt.getMaxVFOV();
2994  }
2995  opt.setVFOV(vfov);
2996  // recalculate panorama height...
2999  );
3000 
3001  DEBUG_INFO ( "new vfov: " << vfov )
3002 };
3003 
3005 {
3006  if(m_mode==mode_layout)
3007  {
3008  double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
3009  m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
3010  m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
3011  m_GLPreview->Refresh();
3012  m_GLOverview->Refresh();
3013  };
3014 };
3015 
3017 {
3019  double hfov = opts.getHFOV();
3020  double vfov = opts.getVFOV();
3021  double maxfov = hfov > vfov ? hfov : vfov;
3022  wxString message;
3023  // If this is set to true, offer rectilinear as an alternative if it fits.
3024  bool rectilinear_option = false;
3025  switch (opts.getProjection()) {
3027  if (maxfov > 120.0) {
3028  // wide rectilinear image
3029  message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
3030  if (vfov < 110) {
3031  message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
3032  } else {
3033  message += _("For a very wide panorama, try equirectangular projection instead.");
3034  }
3035  message += wxT(" ");
3036  message += _("You could also try Panini projection.");
3037  }
3038  break;
3040  if (vfov > 120.0) {
3041  message = _("With a wide vertical field of view, panoramas with cylindrical projection get very stretched at the top and bottom.\nAn equirectangular projection would fit the same content in less vertical space.");
3042  } else rectilinear_option = true;
3043  break;
3045  if (vfov < 110.0 && hfov > 120.0)
3046  {
3047  message = _("Since the vertical field of view is not too wide, you could try setting the panorama projection to cylindrical.\nCylindrical projection preserves vertical lines, unlike equirectangular.");
3048  } else rectilinear_option = true;
3049  break;
3051  if (maxfov < 280.0) {
3052  rectilinear_option = true;
3053  message = _("Stereographic projection is conformal, unlike this Fisheye panorama projection.\nA conformal projection preserves angles around a point, which often makes it easier on the eye.");
3054  }
3055  break;
3057  if (maxfov > 300.0) {
3058  message = _("Panoramas with stereographic projection and a very wide field of view stretch the image around the edges a lot.\nThe Fisheye panorama projection compresses it, so you can fit in a wide field of view and still have a reasonable coverage of the middle.");
3059  } else rectilinear_option = true;
3060  break;
3061  default:
3062  rectilinear_option = true;
3063  }
3064  if (rectilinear_option && maxfov < 110.0) {
3065  message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
3066  }
3067  if (message.IsEmpty()) {
3068  // no message needed.
3069  m_infoBar->Dismiss();
3070  } else {
3071  m_infoBar->ShowMessage(message, wxICON_INFORMATION);
3072  }
3073 };
3074 
3076 {
3077  m_showProjectionHints=new_value;
3079  {
3080  m_infoBar->Dismiss();
3081  };
3082 };
3083 
3085 {
3086  wxMessageBox(_("You have hidden the infobar, which shows hints about selection of projection.\nIf you want to see the bar again, activate the bar in the preferences again."),
3087 #ifdef __WXMSW__
3088  _("Hugin"),
3089 #else
3090  wxT(""),
3091 #endif
3092  wxOK | wxICON_INFORMATION, this);
3093 
3094  wxConfigBase* cfg=wxConfigBase::Get();
3095  cfg->Write(wxT("/GLPreviewFrame/ShowProjectionHints"), false);
3096  m_showProjectionHints=false;
3097  cfg->Flush();
3098  e.Skip();
3099 };
3100 
3101 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
3102 {
3103  if(identify_tool)
3104  {
3105  identify_tool->UpdateWithNewImageSet(new_image_set);
3106  };
3108  {
3110  };
3112  {
3114  };
3115 }
3116 
3118  m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
3119  wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
3120  wxConfigBase* cfg=wxConfigBase::Get();
3121  cfg->Write(wxT("/GLPreviewFrame/PreviewBackground"), c);
3122  cfg->Flush();
3126  redrawPreview();
3127 }
3128 
3131 }
3132 
3133 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
3134 {
3135  if(preview_guide_tool)
3136  {
3137  int selection=e.GetSelection();
3139  //synchronize wxChoice in projection and crop tab
3140  m_GuideChoiceCrop->SetSelection(selection);
3141  m_GuideChoiceProj->SetSelection(selection);
3142  m_GuideChoiceDrag->SetSelection(selection);
3143  redrawPreview();
3144  };
3145 };
3146 
3148 {
3149  int old_selection=m_DragModeChoice->GetSelection();
3150  if(old_selection==wxNOT_FOUND)
3151  {
3152  old_selection=0;
3153  };
3154  m_DragModeChoice->Clear();
3155  m_DragModeChoice->Append(_("normal"));
3156  m_DragModeChoice->Append(_("normal, individual"));
3157  if(newLevel==GUI_EXPERT)
3158  {
3159  m_DragModeChoice->Append(_("mosaic"));
3160  m_DragModeChoice->Append(_("mosaic, individual"));
3161  m_DragModeChoice->SetSelection(old_selection);
3162  }
3163  else
3164  {
3165  if(old_selection>1)
3166  {
3167  m_DragModeChoice->SetSelection(old_selection-2);
3168  }
3169  else
3170  {
3171  m_DragModeChoice->SetSelection(old_selection);
3172  };
3173  };
3174  DragChoiceLayout(m_DragModeChoice->GetSelection());
3175  wxCommandEvent dummy;
3176  OnDragChoice(dummy);
3177 
3178  old_selection=m_OverviewModeChoice->GetSelection();
3179  m_OverviewModeChoice->Clear();
3180  m_OverviewModeChoice->Append(_("Panosphere (outside)"));
3181  m_OverviewModeChoice->Append(_("Panosphere (inside)"));
3182  if(newLevel==GUI_EXPERT)
3183  {
3184  m_OverviewModeChoice->Append(_("Mosaic plane"));
3185  };
3186  if(newLevel==GUI_EXPERT && old_selection==2)
3187  {
3188  m_OverviewModeChoice->SetSelection(2);
3189  }
3190  else
3191  {
3193  m_OverviewModeChoice->SetSelection(0);
3194  };
3195  if(newLevel==GUI_SIMPLE)
3196  {
3197 #ifdef __WXMAC__
3198  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
3199 #endif
3200  if(m_guiLevel!=GUI_SIMPLE)
3201  {
3202  GetMenuBar()->Remove(0);
3203  GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
3204  };
3205  SetTitle(MainFrame::Get()->GetTitle());
3206  }
3207  else
3208  {
3209 #ifdef __WXMAC__
3210  wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
3211 #endif
3212  if(m_guiLevel==GUI_SIMPLE)
3213  {
3214  GetMenuBar()->Remove(0);
3215  GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
3216  };
3217  SetTitle(_("Fast Panorama preview"));
3218  };
3219  m_guiLevel=newLevel;
3220  // update menu items
3221  switch(m_guiLevel)
3222  {
3223  case GUI_SIMPLE:
3224  GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
3225  break;
3226  case GUI_ADVANCED:
3227  GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
3228  break;
3229  case GUI_EXPERT:
3230  GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
3231  break;
3232  };
3233 };
3234 
3235 void GLPreviewFrame::AddUserDefinedSequence(int id, const wxString& desc, const wxString& help)
3236 {
3237  if (id == -1)
3238  {
3239  m_createButton->GetSplitButtonMenu()->AppendSeparator();
3240  }
3241  else
3242  {
3243  m_createButton->GetSplitButtonMenu()->Append(id, desc, help);
3244  };
3245 };
3246 
3247 void GLPreviewFrame::AddUserDefinedAssistant(int id, const wxString& desc, const wxString& help)
3248 {
3249  if (id == -1)
3250  {
3251  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
3252  }
3253  else
3254  {
3255  m_alignButton->GetSplitButtonMenu()->Append(id, desc, help);
3256  };
3257 };
3258 
3259 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
3260 {
3261  MainFrame::Get()->Show();
3262  MainFrame::Get()->Raise();
3263 };
3264 
3265 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
3266 {
3267  Close();
3268 };
3269 
3271 {
3272  if (wxConfig::Get()->Read(wxT("/ShowFisheyeCropHint"), 1l) == 1)
3273  {
3274  // show hint about crop and open tab when requested
3275  wxDialog dlg;
3276  wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("fisheye_show_crop_dlg"));
3277  if (dlg.ShowModal() == wxID_OK)
3278  {
3279  MainFrame::Get()->ShowMaskEditor(0, true);
3280  };
3281  if (XRCCTRL(dlg, "fisheye_crop_dont_ask_checkbox", wxCheckBox)->IsChecked())
3282  {
3283  wxConfig::Get()->Write(wxT("/ShowFisheyeCropHint"), 0l);
3284  };
3285  };
3286 }
3287 
3288 void GLPreviewFrame::OnLoadImages(wxCommandEvent& e)
3289 {
3290  // load all images with default lens type
3291  LoadImages(-1);
3292 }
3293 
3294 void GLPreviewFrame::LoadImages(int preferredLensType)
3295 {
3296  // load the images.
3297  PanoOperation::AddImageOperation addImage(preferredLensType);
3298  HuginBase::UIntSet images;
3299  PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
3300  if(cmd==NULL)
3301  {
3302  return;
3303  }
3304  //distribute images only if the existing images are not connected
3305  //otherwise it would destruct the existing image pattern
3306  const bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
3307 
3308  const long autoAlign = wxConfigBase::Get()->Read(wxT("/Assistant/autoAlign"), HUGIN_ASS_AUTO_ALIGN);
3309  if (autoAlign)
3310  {
3312  wxCommandEvent dummy;
3313  OnAlign(dummy);
3314  }
3315  else
3316  {
3317  std::vector<PanoCommand::PanoCommand*> cmds;
3318  cmds.push_back(cmd);
3319  if(distributeImages)
3320  {
3321  cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
3322  cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
3323  };
3325  combinedCmd->setName("add and distribute images");
3327  if(m_pano.getImage(0).isCircularCrop())
3328  {
3329  // show hint about crop for fisheye images
3330  // skip display if we read the information from our lens database
3331  HuginBase::FileMetaData metaData=m_pano.getImage(0).getFileMetadata();
3332  HuginBase::FileMetaData::const_iterator pos = metaData.find("readProjectionFromDB");
3333  if(!(pos != metaData.end() && pos->second == "true"))
3334  {
3336  };
3337  };
3338  };
3339 }
3340 
3341 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
3342 {
3343  // run default assisant
3344  MainFrame::Get()->RunAssistant(this);
3345 }
3346 
3347 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
3348 {
3349  PanoOutputDialog dlg(this, m_pano, m_guiLevel);
3350  if(dlg.ShowModal()==wxID_OK)
3351  {
3354  );
3355  wxCommandEvent dummy;
3356  MainFrame::Get()->OnDoStitch(dummy);
3357  };
3358 }
3359 
3360 // remove cp, relatively easy, we get the selected cp from the edit cp tool
3361 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
3362 {
3365  // ask user, if pano should be optimized
3366  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3367  bool optimize = false;
3368  if (afterEditCPAction == 0)
3369  {
3370  wxDialog dlg;
3371  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3372  XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were removed from the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(edit_cp_tool->GetFoundCPs().size())));
3373  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3374  dlg.Fit();
3375  optimize = (dlg.ShowModal() == wxID_OK);
3376  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3377  {
3378  if (optimize)
3379  {
3380  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3381  }
3382  else
3383  {
3384  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3385  };
3386  };
3387  }
3388  else
3389  {
3390  optimize = (afterEditCPAction == 1);
3391  }
3392  if (optimize)
3393  {
3394  // invoke optimization routine
3395  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3396  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3397  };
3398 };
3399 
3400 // some helper for cp generation
3401 // maximal width for remapping for cp generating
3402 #define MAX_DIMENSION 1600
3404 {
3405  size_t imgNr;
3406  vigra::BRGBImage image;
3407  vigra::BImage mask;
3408 };
3409 
3410 typedef std::vector<FindStruct> FindVector;
3411 typedef std::multimap<double, vigra::Diff2D> MapPoints;
3412 
3414 
3415 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
3416 {
3418  vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
3420  // some checking of conditions
3421  if (imgs.empty())
3422  {
3423  wxMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
3424 #ifdef __WXMSW__
3425  _("Hugin"),
3426 #else
3427  wxT(""),
3428 #endif
3429  wxOK | wxICON_INFORMATION, this);
3430  return;
3431  };
3432  if (imgs.size() < 2)
3433  {
3434  wxMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
3435 #ifdef __WXMSW__
3436  _("Hugin"),
3437 #else
3438  wxT(""),
3439 #endif
3440  wxOK | wxICON_INFORMATION, this);
3441  return;
3442  };
3443  if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
3444  {
3445  if(wxMessageBox(_("The selected rectangle is very big.\nThis function is only intended for smaller areas. Otherwise unwanted side effect can appear.\n\nProceed anyway?"),
3446 #ifdef __WXMSW__
3447  _("Hugin"),
3448 #else
3449  wxT(""),
3450 #endif
3451  wxYES_NO | wxICON_INFORMATION, this) == wxNO)
3452  {
3453  return;
3454  };
3455  }
3457  opts.setROI(roi);
3458  // don't correct exposure
3459  opts.outputExposureValue = 0;
3460  // don't use GPU for remapping, this interfere with the fast preview window
3461  opts.remapUsingGPU = false;
3462  // rescale if size is too big
3463  if (roi.width() > MAX_DIMENSION)
3464  {
3465  opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
3466  roi = opts.getROI();
3467  };
3468  HuginBase::CPVector cps;
3469  {
3470  ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
3471  // remap all images to panorama projection
3472  FindVector cpInfos;
3473  HuginBase::CPVector tempCps;
3474  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
3475  {
3476  const size_t imgNr = *it;
3477  if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
3478  {
3479  return;
3480  };
3481  FindStruct findStruct;
3482  findStruct.imgNr = imgNr;
3483  // remap image to panorama projection
3484  ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
3485 
3487  HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
3488  // don't correct exposure
3489  srcImg.setExposureValue(0);
3490  remapped->setPanoImage(srcImg, opts, roi);
3491  remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
3492  if (!progress.updateDisplay())
3493  {
3494  delete remapped;
3495  return;
3496  };
3497  findStruct.image = remapped->m_image;
3498  findStruct.mask = remapped->m_mask;
3499  delete remapped;
3500  cpInfos.push_back(findStruct);
3501  };
3502  if (cpInfos.size() > 1)
3503  {
3504  // match keypoints in all image pairs
3505  // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
3506  unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
3507  if (gridx < 1)
3508  {
3509  gridx = 1;
3510  }
3511  unsigned gridy = hugin_utils::roundi(25 / gridx);
3512  if (gridy < 1)
3513  {
3514  gridy = 1;
3515  }
3516  while (roi.width() / gridx < 20 && gridx > 1)
3517  {
3518  --gridx;
3519  };
3520  while (roi.height() / gridy < 20 && gridy > 1)
3521  {
3522  --gridy;
3523  };
3524  // template width
3525  const long templWidth = 20;
3526  // search width
3527  const long sWidth = 100;
3528  // match all images with all
3529  for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
3530  {
3531  if (!progress.updateDisplayValue(_("Matching interest points...")))
3532  {
3533  return;
3534  };
3535  vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
3536  // create a number of sub-regions
3537  std::vector<vigra::Rect2D> rects;
3538  for (unsigned party = 0; party < gridy; party++)
3539  {
3540  for (unsigned partx = 0; partx < gridx; partx++)
3541  {
3542  vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
3543  (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
3544  rect &= vigra::Rect2D(size);
3545  if (rect.width()>0 && rect.height()>0)
3546  {
3547  rects.push_back(rect);
3548  };
3549  };
3550  };
3551 
3552  if (!progress.updateDisplay())
3553  {
3554  return;
3555  };
3556 
3557 #pragma omp parallel for schedule(dynamic)
3558  for (int i = 0; i < rects.size(); ++i)
3559  {
3560  MapPoints points;
3561  vigra::Rect2D rect(rects[i]);
3562  // run interest point detection in sub-region
3563  vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
3564  //check if all points are inside the given image
3565  MapPoints validPoints;
3566  for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
3567  {
3568  if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
3569  {
3570  validPoints.insert(*it);
3571  };
3572  };
3573 
3574  if (!validPoints.empty())
3575  {
3576  // now fine-tune the interest points with all other images
3577  for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
3578  {
3579  unsigned nGood = 0;
3580  // loop over all points, starting with the highest corner score
3581  for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
3582  {
3583  if (nGood >= 2)
3584  {
3585  // we have enough points, stop
3586  break;
3587  }
3588  //check if point is covered by second image
3589  if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
3590  {
3591  continue;
3592  };
3593  // finally fine-tune point
3594  vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
3595  cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
3596  if (res.maxi < 0.9)
3597  {
3598  continue;
3599  }
3600  nGood++;
3601  // add control point
3602  {
3603  hugin_omp::ScopedLock sl(cpLock);
3604  tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
3605  cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
3606  };
3607  };
3608  };
3609  };
3610  };
3611  // free memory
3612  cpInfos[img1].image.resize(0, 0);
3613  cpInfos[img1].mask.resize(0, 0);
3614  };
3615 
3616  // transform coordinates back to image space
3617  for (size_t i = 0; i < tempCps.size(); ++i)
3618  {
3619  HuginBase::ControlPoint cp = tempCps[i];
3620  hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
3621  hugin_utils::FDiff2D p1Img;
3622  HuginBase::PTools::Transform transform;
3623  transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
3624  if (transform.transformImgCoord(p1Img, p1))
3625  {
3626  hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
3627  hugin_utils::FDiff2D p2Img;
3628  transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
3629  if (transform.transformImgCoord(p2Img, p2))
3630  {
3631  cp.x1 = p1Img.x;
3632  cp.y1 = p1Img.y;
3633  cp.x2 = p2Img.x;
3634  cp.y2 = p2Img.y;
3635  cps.push_back(cp);
3636  };
3637  };
3638  };
3639 
3640  if (!cps.empty())
3641  {
3642  // check newly found control points
3643  // create copy
3645  // remove all cps and set only the new found cp
3646  copyPano.setCtrlPoints(cps);
3647  // now create a subpano with only the selected images
3648  HuginBase::Panorama subPano = copyPano.getSubset(imgs);
3649  // clean control points
3650  if (!progress.updateDisplayValue(_("Checking results...")))
3651  {
3652  return;
3653  };
3655  HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
3657  if (!invalidCP.empty())
3658  {
3659  for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
3660  {
3661  cps.erase(cps.begin() + *it);
3662  };
3663  }
3664  // force closing progress dialog
3665  if (!progress.updateDisplayValue())
3666  {
3667  return;
3668  };
3670  // ask user, if pano should be optimized
3671  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3672  bool optimize = false;
3673  if (afterEditCPAction == 0)
3674  {
3675  // close progress window, otherwise the dialog don't autoamtically get the focus
3676  wxYield();
3677  wxDialog dlg;
3678  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3679  XRCCTRL(dlg, "edit_cp_text1", wxStaticText)->SetLabel(wxString::Format(_("%lu control points were added to the panorama.\n\nShould the panorama now be re-optimized?"), static_cast<unsigned long int>(cps.size())));
3680  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3681  dlg.Fit();
3682  optimize = (dlg.ShowModal() == wxID_OK);
3683  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3684  {
3685  if (optimize)
3686  {
3687  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3688  }
3689  else
3690  {
3691  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3692  };
3693  };
3694  }
3695  else
3696  {
3697  optimize = (afterEditCPAction == 1);
3698  }
3699  if (optimize)
3700  {
3701  // invoke optimization routine
3702  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3703  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3704  };
3705  };
3706  };
3707  };
3708  // finally redraw
3709  m_GLPreview->Update();
3710  m_GLPreview->Refresh();
3711 };
3712 
3713 // handle menu close event to redraw preview, so that selection rectangle is hidden
3714 void GLPreviewFrame::OnMenuClose(wxMenuEvent & e)
3715 {
3716  m_GLPreview->Refresh();
3717  e.Skip();
3718 };
3719 
3720 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
3721 {
3722  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
3724 };
3725 
3726 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
3727 {
3728  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 1l);
3730 };
3731 
3733 {
3734  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 2l);
3736 };
3737 
3739 {
3740  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 3l);
3742 };
3743 
3745 {
3746  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), true);
3747  m_selectKeepSelection = true;
3748 };
3749 
3751 {
3752  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), false);
3753  m_selectKeepSelection = false;
3754 };
HuginBase::UIntSet GetDragGroupImages()
AlphaImage m_mask
corresponding alpha channel
Definition: ROIImage.h:274
#define DEBUG_INFO(msg)
Definition: utils.h:69
int floori(double x)
Definition: hugin_math.h:65
void setConstantOn(bool constant_on_in)
tool for the manipulation of the opengl &#39;camera&#39; properties It handles rotation of the camera positio...
wxSlider * m_HFOVSlider
Base class for all panorama commands.
Definition: Command.h:38
wxTextCtrl * m_ROITopTxt
wxTextCtrl * m_rangeCompressionTextCtrl
PlaneOverviewCameraTool * plane_overview_camera_tool
SelectAllMode m_selectAllMode
HuginBase::Panorama & m_pano
Definition: PreviewFrame.h:93
Allow the user to change the cropping region by dragging it in the fast preview.
int gcd(int a, int b)
function to calculate greated common divisor using Euclidean algorithm both arguments should be &gt;=0 ...
Definition: hugin_math.cpp:35
PanoramaOptions::ProjectionFormat getProjection() const
#define HUGIN_SHOW_PROJECTION_HINTS
void OnRangeCompressionDecrease(wxSpinEvent &e)
std::vector< UIntSet > getHDRStacks(const PanoramaData &pano, UIntSet allImgs, PanoramaOptions opts)
returns vector of set of output stacks
Definition: LayerStacks.cpp:35
void AddDragTool(DragTool **drag_tool_in)
wxSpinButton * m_exposureSpinBut
implementation of huginApp Class
update variables of a group of images
Definition: PanoCommand.h:174
declaration of functions to handle stacks and layers
std::vector< wxToggleButton * > m_ToggleButtons
void OnRemoveCP(wxCommandEvent &e)
handler to remove cp
PreviewCropTool * crop_tool
void OnControlPoint(wxCommandEvent &e)
PreviewDifferenceTool * panosphere_difference_tool
std::set< Tool * > ActivateTool(Tool *tool)
Definition: ToolHelper.cpp:53
void OnCreate(wxCommandEvent &e)
wxGLContext * GetContext()
Definition: GLViewer.h:78
PreviewIdentifyTool * identify_tool
void SetStatusMessage(wxString message)
The OpenGL preview frame.
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory, checks if operation is enabled
void setHeight(unsigned int h)
set panorama height
void OnIdentify(wxCommandEvent &e)
pano_projection_features m_projFeatures
int roundi(T x)
Definition: hugin_math.h:73
wxChoice * m_DragModeChoice
wxColour GetPreviewBackgroundColor()
void OnShowAll(wxCommandEvent &e)
void StorePositionAndSize()
store position and size of window in wxConfig
#define HUGIN_PREVIEW_BACKGROUND
void setPanoImage(const SrcPanoImage &src, const PanoramaOptions &dest, vigra::Rect2D roi)
static double calcMeanExposure(const PanoramaData &pano)
vigra::BImage mask
wxBoxSizer * m_topsizer
bool str2double(const wxString &s, double &d)
Definition: wxPlatform.cpp:37
void AddUserDefinedAssistant(int id, const wxString &desc, const wxString &help)
adds the given user defined assistant to SplitButton menu
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
Definition: Panorama.cpp:1620
PreviewDragTool * drag_tool
GLwxAuiFloatingFrame * CreateFloatingFrame(wxWindow *parent, const wxAuiPaneInfo &p)
std::vector< ImageToogleButtonEventHandler * > toogle_button_event_handlers
PanosphereOverviewCameraTool * panosphere_overview_camera_tool
void OnColorPicker(wxCommandEvent &e)
event handler when starting color picker
tool for the manipulation of the opengl &#39;camera&#39; properties It handles zooming in/out of the main pre...
center panorama horizontically
Definition: PanoCommand.h:250
void ClearDragGroupImages(bool update_check_box=true)
bool isCircularCrop() const
returns true, if projection requires cicular crop
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Definition: Panorama.cpp:1551
void ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box=true)
void OnVFOVChanged(wxCommandEvent &e)
GuiLevel m_guiLevel
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:300
ImageToogleButtonEventHandler(unsigned int image_number, wxToggleButton *identify_button_in, HuginBase::Panorama *m_pano)
#define HUGIN_CONV_FILENAME
Definition: platform.h:40
wxPanel * m_overviewCommandPanel
void OnOverviewToggle(wxCommandEvent &e)
wxTextCtrl * m_ROIRightTxt
void SetPhotometricCorrect(bool state)
Definition: GLViewer.cpp:288
SplitButton * m_createButton
CorrelationResult PointFineTune(const IMAGET &templImg, ACCESSORT access_t, vigra::Diff2D templPos, int templSize, const IMAGES &searchImg, ACCESSORS access_s, vigra::Diff2D searchPos, int sWidth)
fine tune a point with normalized cross correlation
Definition: Correlation.h:504
#define DEBUG_TRACE(msg)
Definition: utils.h:67
void OnDecreaseExposure(wxSpinEvent &e)
wxBitmapButton * m_defaultExposureBut
void OnEnter(wxMouseEvent &e)
void RunAssistant(wxWindow *mainWin, const wxString &userdefinedAssistant=wxEmptyString)
Definition: MainFrame.cpp:2431
void registerPTWXDlgFcn()
Definition: PTWXDlg.cpp:173
void OnSwitchPreviewGrid(wxCommandEvent &e)
event handler for switch on/off grid on preview
unsigned int getHeight() const
get panorama height
void SetActive(bool active)
Definition: GLViewer.h:75
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
void OnShowMainFrame(wxCommandEvent &e)
event handler to show main frame
some helper classes for graphes
GLPreview * m_GLPreview
void Resized(wxSizeEvent &e)
Definition: GLViewer.cpp:355
double getMaxHFOV() const
get maximum possible hfov with current projection
wxColour m_preview_background_color
virtual void setName(const std::string &newName)
sets the name for the command
Definition: Command.cpp:88
PreviewLayoutLinesTool * m_plane_layoutLinesTool
std::vector< wxCheckBox * > m_GroupToggleButtons
void AddImageToDragGroup(unsigned int image_nr, bool update_check_box=true)
void deregisterPTWXDlgFcn()
Definition: PTWXDlg.cpp:180
virtual void DeactivateTool(Tool *tool)
Definition: ToolHelper.cpp:60
Dialog for setting output parameters for simple user interface.
wxChoice * m_ProjectionChoice
Definition: PreviewFrame.h:100
std::size_t getNrOfCtrlPoints() const
number of control points
Definition: Panorama.h:306
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition: stl_utils.h:74
wxMenu * GetSplitButtonMenu()
returns a pointer to the drop down menu
Definition: SplitButton.cpp:64
#define DEBUG_ASSERT(cond)
Definition: utils.h:80
PreviewIdentifyTool * plane_overview_identify_tool
void OnSelectDarkestMenu(wxCommandEvent &e)
HuginBase::ImageCache::ImageCacheRGB8Ptr ImageCacheRGB8Ptr
Definition: wxImageCache.h:33
Translate the panorama.
Definition: PanoCommand.h:462
void setProjectionParameters(const std::vector< double > &params)
set the optional parameters (they need to be of the correct size)
PreviewPanoMaskTool * pano_mask_tool
simple class that forward the drop to the mainframe
Definition: MainFrame.h:61
END_EVENT_TABLE()
include file for the hugin project
#define MAX_DIMENSION
void SetMenuProcessed()
reset popup menu status
void ForceRequireRedraw()
Definition: ViewState.cpp:439
wxNotebook * m_tool_notebook
void InitPreviews()
init previews
virtual void run()
runs the algorithm.
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition: Panorama.h:319
PreviewControlPointTool * preview_control_point_tool
std::vector< wxPanel * > m_ToggleButtonPanel
std::vector< PreviewIdentifyTool ** > identify_tools
void UpdateRoiDisplay(const HuginBase::PanoramaOptions opts)
update display of ROI
void OnPhotometric(wxCommandEvent &e)
wxTextCtrl * m_ROILeftTxt
remove several control points
Definition: PanoCommand.h:307
represents a control point
Definition: ControlPoint.h:38
PreviewDifferenceTool * plane_difference_tool
std::vector< PreviewIdentifyTool ** > identify_tools
Definition of PanoOperation class.
void findInterestPointsPartial(vigra::triple< ImageIter, ImageIter, ImageAcc > img, const vigra::Rect2D &rect, double scale, unsigned nPoints, std::multimap< double, vigra::Diff2D > &points)
void OnChange(wxCommandEvent &e)
void RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box=true)
wxChoice * m_GuideChoiceCrop
PanosphereOverviewOutlinesTool * overview_outlines_tool
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition: ImageGraph.h:50
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition: utils.cpp:228
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition: huginApp.cpp:641
PanosphereSphereTool * panosphere_sphere_tool
void DeactivateTool(Tool *tool)
Definition: ToolHelper.cpp:703
void FillBlendChoice()
fills the blend wxChoice with all valid blend modes and restore the last used one ...
void OnActivate(wxActivateEvent &evt)
wxChoice * m_GuideChoiceDrag
PanoCommand to combine other PanoCommands.
Definition: PanoCommand.h:39
Panorama duplicate() const
duplicate the panorama
Definition: Panorama.cpp:1653
wxStaticBoxSizer * m_ToggleButtonSizer
void OnLeave(wxMouseEvent &e)
void OnSetCropAspect(wxCommandEvent &e)
event handler to set fixed aspect ratio of crop
void OnAutocropOutside(wxCommandEvent &e)
static hugin_omp::Lock cpLock
std::vector< LensInfo > LensInfoVector
vector of LensInfo to hold all available lens types
Definition: LensTools.h:48
std::set< unsigned int > UIntSet
Definition: PanoramaData.h:51
helper for OpenMP
set the panorama options
Definition: PanoCommand.h:418
void OnDefaultExposure(wxCommandEvent &e)
wxSlider * m_VFOVSlider
void OnOverviewModeChoice(wxCommandEvent &e)
algorithms for remove control points by statistic method
void OnProjParameterChanged(wxCommandEvent &e)
#define DEBUG_WARN(msg)
Definition: utils.h:74
HuginBase::PanoramaOptions GetNewPanoramaOptions()
Draws guide lines over the panorama in fast preview window.
void LoadOpenGLLayout()
loads the layout of the OpenGL windows and restores it
wxChoice * m_ProjectionChoice
Finds the topmost image underneath the mouse pontier, cancel it&#39;s normal drawing, and then subtract i...
const vigra::Rect2D & getROI() const
void SetMode(OverviewMode mode)
Definition: GLViewer.cpp:491
Model for a panorama.
Definition: Panorama.h:152
wxSpinButton * m_rangeCompressionSpinBut
void OnHFOVChanged(wxCommandEvent &e)
void OnExposureChanged(wxCommandEvent &e)
wxMenu * m_filemenuSimple
wxBoxSizer * m_ButtonSizer
virtual ~GLPreviewFrame()
dtor.
PreviewLayoutLinesTool * m_panosphere_layoutLinesTool
void OnStackAutocrop(wxCommandEvent &e)
#define PF_STYLE
GLwxAuiManager * m_mgr
The dock manager.
void MakePreviewTools(PreviewToolHelper *helper)
void SetMode(int newMode)
virtual void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
notifies about changes to images
VariableMapVector getVariables() const
get variables of this panorama
Definition: Panorama.cpp:118
void OnFullScreen(wxCommandEvent &e)
event handler for full screen
void OnSelectMedianMenu(wxCommandEvent &e)
std::vector< wxSlider * > m_projParamSlider
wxScrolledWindow * m_ButtonPanel
void resetProjectionParameters()
sets the optional parameters to their default values
void SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box=true)
std::size_t getNrOfImages() const
number of images.
Definition: Panorama.h:205
static MainFrame * Get()
hack.. kind of a pseudo singleton...
Definition: MainFrame.cpp:2169
wxTextCtrl * m_VFOVText
Definition of PanoOutputDialog class.
The PreviewCropTool shows lines between the ends of control points in the fast preview.
WXIMPEX HuginLensTools::LensInfoVector GetLensProjectionList()
return a vector with all available projections
Definition: LensTools.cpp:45
interface to ToolHelper for drawing guide lines over pano
void AddUserDefinedSequence(int id, const wxString &desc, const wxString &help)
adds the given user defined output sequence to SplitButton menu
void SetGuiLevel(GuiLevel newLevel)
sets the gui level
void OnEnter(wxMouseEvent &e)
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be &#39;add&#39; method?)
Definition: Panorama.cpp:449
SplitButton * m_selectAllButton
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Store window size and position in configfile/registry.
Definition: LensCalApp.cpp:212
float pow(float a, double b)
Definition: utils.h:181
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
void redrawPreview()
Display an updated version of the preview images.
wxMenu * LoadMenu(const wxString &name)
loads the drop down menu from the XRC ressource
void remapImage(vigra::triple< ImgIter, ImgIter, ImgAccessor > srcImg, vigra_ext::Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
remap a image without alpha channel
PreviewIdentifyTool * panosphere_overview_identify_tool
virtual vigra::Rect2D getResultOptimalROI()
return the ROI structure?, for now area
void OnSelectKeepSelection(wxCommandEvent &e)
wxMenu * m_filemenuAdvanced
double getMaxVFOV() const
get maximum possible vfov with current projection
Definition of dialog for selecting and editing aspect ratios of crop.
virtual double getResultHeight()
Definition: FitPanorama.h:75
std::vector< FindStruct > FindVector
PanoOperation to add several user selected images to the panorama.
Definition: PanoOperation.h:73
PlaneOverviewOutlinesTool * plane_overview_outlines_tool
std::vector< wxTextCtrl * > m_projParamTextCtrl
Maximum of correlation, position and value.
Definition: Correlation.h:56
HuginBase::Panorama * m_pano
std::string getLastCommandName() const
returns the name of the last command
wxInfoBar * m_infoBar
Bar for context sensitive projection information.
void OnToolModeChanging(wxNotebookEvent &e)
event handler for blocking changing mode when panorama contains no images
wxToggleButton * m_editCP_togglebutton
OverviewMode GetMode()
Definition: GLViewer.h:153
wxwindows specific panorama commands
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
Definition: SrcPanoImage.h:55
SplitButton * m_loadImagesButton
std::vector< HuginBase::UIntVector > getSortedStacks(const HuginBase::Panorama *pano)
returns vector of UIntVector with image numbers of each stack sorted by exposure
PreviewControlPointTool * plane_control_point_tool
distributes all images above the sphere, for the assistant
Definition: PanoCommand.h:649
wxPanel * m_projection_panel
void OnRangeCompressionChanged(wxCommandEvent &e)
void SetShowProjectionHints(bool new_value)
set status if projection hints should be shown or not
void UpdateIdentifyTools(std::set< unsigned int > new_image_set)
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Restore window size and position from configfile/registry.
Definition: LensCalApp.cpp:158
static GlobalCmdHist & getInstance()
PanosphereOverviewToolHelper * panosphere_overview_helper
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:294
std::multimap< double, vigra::Diff2D > MapPoints
implementation of PanosphereSphereTool Class
void MakePanosphereOverviewTools(PanosphereOverviewToolHelper *helper)
void ShowMaskEditor(size_t imgNr, bool switchToCropMode=false)
opens the mask/crop editor with the given image selected
Definition: MainFrame.cpp:2040
void SetGuideStyle(const Guides newGuideStyle)
sets the guide style to the given style
std::vector< ImageGroupButtonEventHandler * > toggle_group_button_event_handlers
wxToggleButton * m_identify_togglebutton
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
void OnProjectionChoice(wxCommandEvent &e)
PreviewControlPointTool * panosphere_control_point_tool
PanosphereOverviewProjectionGridTool * overview_projection_grid
Tool to delete all cp in a selected rectangle.
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
Definition: utils.h:114
double GetSelectedAspectRatio() const
returns the selected aspect ratio
VisualizationState * m_visualization_state
Definition: GLViewer.h:71
void EnableGroupCheckboxes(bool isShown)
changes the visibility of the group check boxes
void OnSelectMode(wxNotebookEvent &e)
event handler for selection of new mode
void setROI(const vigra::Rect2D &val)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
Definition: ROIImage.h:287
void ShowFisheyeCropHint()
void KeypressEvent(int keycode, int modifiers, bool pressed)
Definition: ToolHelper.cpp:165
void DragChoiceLayout(int index)
void OnSelectBrightestMenu(wxCommandEvent &e)
void SetBitmap(const wxBitmap &bitmap)
sets bitmap and direction
straighten panorama horizontically
Definition: PanoCommand.h:259
void OnTrackChangeFOV(wxScrollEvent &e)
compute interest points
The PreviewLayoutLinesTool handles the lines connecting images in the layout view of the fast preview...
UIntSet getActiveImages() const
get active images
Definition: Panorama.cpp:1585
void MakePlaneOverviewTools(PlaneOverviewToolHelper *helper)
#define HUGIN_ASS_AUTO_ALIGN
void OnLayoutScaleChange(wxScrollEvent &e)
event handler for change scale of layout mode
OverviewDragTool * overview_drag_tool
GLOverview * m_GLOverview
bool m_selectKeepSelection
GLPreviewFrame(wxFrame *frame, HuginBase::Panorama &pano)
ctor.
void OnCenterHorizontally(wxCommandEvent &e)
virtual void SetLayoutScale(double scale)
Definition: GLViewer.cpp:313
void OnROIChanged(wxCommandEvent &e)
event handler for changed roi
wxChoice * m_BlendModeChoice
std::vector< DragTool ** > drag_tools
wxBoxSizer * m_projParamSizer
tool to draw a whiteish transparent sphere for the panosphere
void OnLoadImages(wxCommandEvent &e)
void ShowProjectionWarnings()
Tell the user anything suspicious about the projection choice.
void OnUserExit(wxCommandEvent &e)
user wants to quit program
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void OnGuideChanged(wxCommandEvent &e)
event handler when user selects different guide
void UpdateWithNewImageSet(std::set< unsigned int > new_image_set)
void OnShowNone(wxCommandEvent &e)
void addObserver(PanoramaObserver *o)
add a panorama observer.
Definition: Panorama.cpp:1546
void OnDoStitch(wxCommandEvent &e)
Definition: MainFrame.cpp:1691
void setDragMode(DragMode drag_mode)
Definition: DragTool.cpp:47
unsigned int getWidth() const
include file for the hugin project
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:306
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
void OnMenuClose(wxMenuEvent &e)
handle menu close event
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition: Panorama.h:481
void OnSelectAllMenu(wxCommandEvent &e)
handle all options of select all context menu
void OnSelectResetSelection(wxCommandEvent &e)
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
virtual double getResultHorizontalFOV()
Definition: FitPanorama.h:68
virtual vigra::Rect2D getResultOptimalROI()
returns the found crop rect
void OnResetCrop(wxCommandEvent &e)
event handler to reset crop area
UIntSet getCPoutsideLimit(Panorama pano, double n, bool skipOptimisation, bool includeLineCp)
optimises the whole panorama and removes all control points with error &gt; mean+n*sigma ...
Definition: CleanCP.cpp:123
PreviewToolHelper * preview_helper
wxTextCtrl * m_ROIBottomTxt
bool Enable(bool enable=true) override
enable or disable the control
Components GetComponents()
find all connected components
Definition: ImageGraph.cpp:101
subclass for a floating frame of the dock manager
void Redraw()
Definition: GLViewer.cpp:384
SplitButton * m_alignButton
wxToggleButton * m_identify_button
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
void OnChange(wxCommandEvent &e)
void OnIncreaseExposure(wxSpinEvent &e)
bool UpdateOverviewMode(int newMode)
updates the mode of the overview window
wxToggleButton * m_colorpicker_togglebutton
void OnRangeCompressionIncrease(wxSpinEvent &e)
static T max(T x, T y)
Definition: svm.cpp:65
bool m_showProjectionHints
Holds transformations for Image -&gt; Pano and the other way.
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
Definition: ViewState.cpp:120
void OnCreateCP(wxCommandEvent &e)
handler for creating cp in pano space
#define DEBUG_DEBUG(msg)
Definition: utils.h:68
DragMode getDragMode()
Definition: DragTool.cpp:52
unsigned int optimize(PanoramaData &pano, const char *userScript)
optimize the images imgs, for variables optvec, using vars as start.
void OnPreviewBackgroundColorChanged(wxColourPickerEvent &e)
event handler when user changes background color
void SetViewerBackground(wxColour col)
Definition: GLViewer.cpp:484
tool for manipulation of the opengl &#39;camera&#39; properties It handles the position of the camera in 3 di...
void OnDragChoice(wxCommandEvent &e)
hugin_utils::FDiff2D maxpos
Definition: Correlation.h:64
PreviewColorPickerTool * color_picker_tool
void OnChangeFOV(wxScrollEvent &e)
std::vector< ControlPoint > CPVector
Definition: ControlPoint.h:99
interface of ToolHelper for deleting control points in the pano space
wxFileHistory * GetFileHistory()
Definition: MainFrame.h:187
platform/compiler specific stuff.
void SetPreviewBackgroundColor(wxColour c)
sets the sphere background color
void updateBlendMode()
Update tools and GUI elements according to blend mode choice.
bool HasNonZeroTranslationPlaneParameters()
check, if panorama has non-zero translation plane parameters
void OnEditCPTool(wxCommandEvent &e)
event handler when starting edit cp tool
PlaneOverviewToolHelper * plane_overview_helper
HuginBase::UIntSet GetFoundCPs()
return set of found control points
PreviewEditCPTool * edit_cp_tool
The PreviewColorPickerTool allows to select a region in the panorama which should be grey...
For projections where the output range is limited, but the approximatly remaped images can extend thi...
void OnBlendChoice(wxCommandEvent &e)
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition: Panorama.h:211
wxTextCtrl * m_exposureTextCtrl
void OnShowEvent(wxShowEvent &e)
GuiLevel
Definition: GuiLevel.h:31
void OnAutocrop(wxCommandEvent &e)
vigra::BRGBImage image
bool needsOptimization()
true if control points or lens variables have been changed after the last optimisation ...
Definition: Panorama.h:614
std::vector< wxStaticText * > m_projParamNamesLabel
PreviewProjectionGridTool * preview_projection_grid
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition: stl_utils.h:81
update global white balance
Definition: PanoCommand.h:626
customized subclass of the dock manager, created just for the purpose to create a workaround for the ...
void KeyDown(wxKeyEvent &e)
ProjectionFormat
Projection of final panorama.
HuginBase::Panorama & m_pano
void setSrcImage(unsigned int nr, const SrcPanoImage &img)
set input image parameters
PreviewGuideTool * preview_guide_tool
void SetLabel(const wxString &label)
set the label string
Allows the user to change the yaw, pitch and roll of a connected component of images by dragging them...
Definition: DragTool.h:50
void ResetTranslationPlaneParameters()
resets all translation plane parameters to zero
virtual void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
add multiple control points
Definition: PanoCommand.h:281
wxChoice * m_GuideChoiceProj
PreviewCameraTool * camera_tool
ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame *frame_in, HuginBase::Panorama *m_pano)
void OnStraighten(wxCommandEvent &e)
All variables of a source image.
Definition: SrcPanoImage.h:194
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
void SetDirtyViewport()
Definition: ViewState.h:249
static ViewState * m_view_state
Definition: GLViewer.h:72
Panorama image options.
PreviewLayoutLinesTool * m_preview_layoutLinesTool
void SetZoomLevel(const float new_zoom)
Definition: ViewState.cpp:483
vigra::Size2D getSize() const
get size of output image
static bool CheckOpenGLCanDifference()
check, if graphic card supports the necessary modes for difference tool call this procedure first...
Rotate the panorama.
Definition: PanoCommand.h:448
void UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
updates the global white balance
void SetImageButtonColour(unsigned int image_nr, unsigned char red, unsigned char green, unsigned char blue)
void ResetPreviewZoom()
reset zoom level for preview window
vigra::Rect2D GetSelectedROI()
returns selected ROI
void OnClose(wxCloseEvent &e)
void SetUpContext()
Definition: GLViewer.cpp:121
struct to hold a image state for stitching
wxString Components2Str(const HuginGraph::ImageGraph::Components &comp)
Definition: huginApp.cpp:84
static T min(T x, T y)
Definition: svm.cpp:62
HuginBase::UIntSet imageDragGroup
void OnNumTransform(wxCommandEvent &e)
void OnAlign(wxCommandEvent &e)
Visually connect the image numbers with the image on the preview.
wxTextCtrl * m_HFOVText
wxChoice * m_OverviewModeChoice
PreviewDifferenceTool * difference_tool
void OnHideProjectionHints(wxCommandEvent &e)
event handler when user hides the infobar
void createTransform(const vigra::Diff2D &srcSize, VariableMap srcVars, Lens::LensProjectionFormat srcProj, const vigra::Diff2D &destSize, PanoramaOptions::ProjectionFormat destProj, const std::vector< double > &destProjParam, double destHFOV, const vigra::Diff2D &origSrcSize)
initialize pano-&gt;image transformation
void OnProjParameterReset(wxCommandEvent &e)
event handler for reset projection parameters
void TurnOffTools(std::set< Tool * > tools)
void LoadImages(int preferredLensType)
HuginBase::Panorama * m_pano
void KeyUp(wxKeyEvent &e)
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
GLPreviewFrame * frame
void OnLeave(wxMouseEvent &e)
void OnFitPano(wxCommandEvent &e)
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition: ImageGraph.h:44