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 #define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
126 
127 GLwxAuiFloatingFrame* GLwxAuiManager::CreateFloatingFrame(wxWindow* parent, const wxAuiPaneInfo& p)
128 {
129  DEBUG_DEBUG("CREATING FLOATING FRAME");
130  frame->PauseResize();
131  GLwxAuiFloatingFrame* fl_frame = new GLwxAuiFloatingFrame(parent, this, p);
132  DEBUG_DEBUG("CREATED FLOATING FRAME");
133  return fl_frame;
134 }
135 
136 GLwxAuiFloatingFrame::GLwxAuiFloatingFrame(wxWindow* parent, GLwxAuiManager* owner_mgr, const wxAuiPaneInfo& pane, wxWindowID id, long style) :
137  wxAuiFloatingFrame(parent, (wxAuiManager*)owner_mgr, pane, id, style)
138 {
139  Bind(wxEVT_ACTIVATE, &GLwxAuiFloatingFrame::OnActivate, this);
140 }
141 
142 void GLwxAuiFloatingFrame::OnActivate(wxActivateEvent& evt)
143 {
144  DEBUG_DEBUG("FRAME ACTIVATE");
145  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
146  frame->ContinueResize();
147  evt.Skip();
148 }
149 
151 {
152  DEBUG_DEBUG("FRAME ON MOVE FINISHED");
153  GLPreviewFrame * frame = ((GLwxAuiManager*) GetOwnerManager())->getPreviewFrame();
154  frame->PauseResize();
155  wxAuiFloatingFrame::OnMoveFinished();
156  DEBUG_DEBUG("FRAME AFTER ON MOVE FINISHED");
157 }
158 
160 {
161  DEBUG_DEBUG("PAUSE RESIZE");
162  GLresize = false;
163 }
164 
166 {
167  GLresize = true;
168  wxSizeEvent event = wxSizeEvent(wxSize());
169  m_GLPreview->Resized(event);
170  m_GLOverview->Resized(event);
171 }
172 
173 #include <iostream>
175  : wxFrame(frame,-1, _("Fast Panorama preview"), wxDefaultPosition, wxDefaultSize,
176  PF_STYLE),
177  m_pano(pano)
178 {
179 
180  DEBUG_TRACE("");
181 
182  // initialize pointer
183  preview_helper = NULL;
185  plane_overview_helper = NULL;
186  crop_tool = NULL;
187  drag_tool = NULL;
188  color_picker_tool = NULL;
189  edit_cp_tool = NULL;
190  overview_drag_tool = NULL;
191  identify_tool = NULL ;
192  camera_tool = NULL;
195  difference_tool = NULL;
196  plane_difference_tool = NULL;
198  pano_mask_tool = NULL;
199  preview_guide_tool = NULL;
201 #ifdef __WXGTK__
202  loadedLayout=false;
203 #endif
204 
205  m_mode = -1;
206  m_oldProjFormat = -1;
207  // add a status bar
208  CreateStatusBar(3);
209  int widths[3] = {-3, 150, 150};
210  SetStatusWidths(3, widths);
211  SetStatusText(wxT(""),1);
212  SetStatusText(wxT(""),2);
213  wxConfigBase * cfg = wxConfigBase::Get();
214 
215  wxPanel *tool_panel = wxXmlResource::Get()->LoadPanel(this,wxT("mode_panel"));
216  XRCCTRL(*this,"preview_center_tool",wxButton)->SetBitmapMargins(0,5);
217  XRCCTRL(*this,"preview_fit_pano_tool",wxButton)->SetBitmapMargins(0,5);
218  XRCCTRL(*this,"preview_straighten_pano_tool",wxButton)->SetBitmapMargins(0,5);
219  XRCCTRL(*this,"preview_fit_pano_tool2",wxButton)->SetBitmapMargins(0,5);
220  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
221  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->SetBitmapMargins(0,5);
222  XRCCTRL(*this, "preview_autocrop_outside_tool", wxButton)->SetBitmapMargins(0, 5);
223 
224  m_tool_notebook = XRCCTRL(*this, "mode_toolbar_notebook", wxNotebook);
225  m_tool_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &GLPreviewFrame::OnSelectMode, this);
226  m_tool_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGING, &GLPreviewFrame::OnToolModeChanging, this);
227  m_identify_togglebutton = XRCCTRL(*this, "preview_identify_toggle_button", wxToggleButton);
228  m_identify_togglebutton->SetBitmapMargins(0, 5);
229  m_identify_togglebutton->Bind(wxEVT_TOGGLEBUTTON, &GLPreviewFrame::OnIdentify, this);
230  m_colorpicker_togglebutton = XRCCTRL(*this, "preview_color_picker_toggle_button", wxToggleButton);
231  m_colorpicker_togglebutton->SetBitmapMargins(0, 5);
232  m_colorpicker_togglebutton->Bind(wxEVT_TOGGLEBUTTON, &GLPreviewFrame::OnColorPicker, this);
233  m_editCP_togglebutton = XRCCTRL(*this, "preview_edit_cp_toggle_button", wxToggleButton);
234  m_editCP_togglebutton->SetBitmapMargins(0, 5);
235  m_editCP_togglebutton->Bind(wxEVT_TOGGLEBUTTON, &GLPreviewFrame::OnEditCPTool, this);
236 
237  //build menu bar
238 #ifdef __WXMAC__
239  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
240 #endif
241  wxMenuBar* simpleMenu=wxXmlResource::Get()->LoadMenuBar(this, wxT("preview_simple_menu"));
242  m_filemenuSimple=wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu"));
243  m_filemenuAdvanced = wxXmlResource::Get()->LoadMenu(wxT("preview_file_menu_advanced"));
244  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuSimple->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
245  MainFrame::Get()->GetFileHistory()->UseMenu(m_filemenuAdvanced->FindItem(XRCID("menu_mru_preview"))->GetSubMenu());
246  MainFrame::Get()->GetFileHistory()->AddFilesToMenu();
247  simpleMenu->Insert(0, m_filemenuSimple, _("&File"));
248  SetMenuBar(simpleMenu);
249 
250  // initialize preview background color
251  wxString c = cfg->Read(wxT("/GLPreviewFrame/PreviewBackground"),wxT(HUGIN_PREVIEW_BACKGROUND));
252  m_preview_background_color = wxColour(c);
253  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->SetColour(m_preview_background_color);
254  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Refresh();
255  XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->Update();
256 
257  m_topsizer = new wxBoxSizer( wxVERTICAL );
258 
259  wxPanel * toggle_panel = new wxPanel(this);
260 
261  bool overview_hidden;
262  cfg->Read(wxT("/GLPreviewFrame/overview_hidden"), &overview_hidden, false);
263  GetMenuBar()->FindItem(XRCID("action_show_overview"))->Check(!overview_hidden);
264 
265  m_ToggleButtonSizer = new wxStaticBoxSizer(
266  new wxStaticBox(toggle_panel, -1, _("displayed images")),
267  wxHORIZONTAL );
268  toggle_panel->SetSizer(m_ToggleButtonSizer);
269 
270  m_ButtonPanel = new wxScrolledWindow(toggle_panel, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
271  //Horizontal scroll bars only
272  m_ButtonPanel->SetScrollRate(10, 0);
273  m_ButtonSizer = new wxBoxSizer(wxHORIZONTAL);
274  m_ButtonPanel->SetAutoLayout(true);
275  m_ButtonPanel->SetSizer(m_ButtonSizer);
276 
277  wxPanel *panel = new wxPanel(toggle_panel);
278  wxBitmapBundle bitmapBundle=wxBitmapBundle::FromSVGFile(huginApp::Get()->GetXRCPath() + "data/preview_show_all.svg", wxSize(32, 32));
279  m_selectAllButton = new SplitButton(panel, ID_SHOW_ALL, _("All"), wxDefaultPosition, wxDefaultSize);
280  m_selectAllButton->SetBitmap(bitmapBundle);
281  //m_selectAllButton->SetBitmapMargins(5, 0);
282  m_selectAllButton->LoadMenu(wxT("preview_select_menu"));
283  m_selectAllButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnShowAll, this);
284  // read last used setting
285  long mode = cfg->Read(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
286  m_selectAllMode = static_cast<SelectAllMode>(mode);
287  switch (m_selectAllMode)
288  {
290  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectMedian"), true);
291  break;
293  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectDarkest"), true);
294  break;
296  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectBrightest"), true);
297  break;
298  case SELECT_ALL_IMAGES:
299  default:
300  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_selectAll"), true);
301  break;
302  };
303  m_selectKeepSelection = (cfg->Read(wxT("/GLPreviewFrame/SelectAllKeepSelection"), 1l) == 1l);
305  {
306  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_keepCurrentSelection"), true);
307  }
308  else
309  {
310  m_selectAllButton->GetSplitButtonMenu()->Check(XRCID("selectMenu_resetSelection"), true);
311  };
312  bitmapBundle=wxBitmapBundle::FromSVGFile(huginApp::Get()->GetXRCPath() + "data/preview_show_none.svg", wxSize(32, 32));
313  wxButton* select_none = new wxButton(panel, ID_SHOW_NONE, _("None"));
314  select_none->SetBitmap(bitmapBundle, wxLEFT);
315  select_none->SetBitmapMargins(5,0);
316  select_none->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnShowNone, this);
317 
318  wxBoxSizer *sizer = new wxBoxSizer(wxHORIZONTAL);
319  sizer->Add(m_selectAllButton,0,wxALIGN_CENTER_VERTICAL | wxLEFT | wxTOP | wxBOTTOM,5);
320  sizer->Add(select_none,0,wxALIGN_CENTER_VERTICAL | wxRIGHT | wxTOP | wxBOTTOM,5);
321  panel->SetSizer(sizer);
322  m_ToggleButtonSizer->Add(panel, 0, wxALIGN_CENTER_VERTICAL);
323  m_ToggleButtonSizer->Add(m_ButtonPanel, 1, wxALIGN_CENTER_VERTICAL, 0);
324 
325  m_topsizer->Add(tool_panel, 0, wxEXPAND | wxALL, 2);
326  m_topsizer->Add(toggle_panel, 0, wxEXPAND | wxBOTTOM, 5);
327 
328  m_infoBar = new wxInfoBar(this);
329  m_infoBar->AddButton(ID_HIDE_HINTS,_("Hide"));
331  m_topsizer->Add(m_infoBar, 0, wxEXPAND);
332 
333  //create panel that will hold gl canvases
334  wxPanel * vis_panel = new wxPanel(this);
335 
336  wxPanel * preview_panel = new wxPanel(vis_panel);
337  wxPanel * overview_panel = new wxPanel(vis_panel);
338 
339  // create our Viewers
340  int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0};
341  m_GLPreview = new GLPreview(preview_panel, pano, args, this);
342  m_GLOverview = new GLOverview(overview_panel, pano, args, this, m_GLPreview->GetContext());
344 
345 #ifdef __WXGTK__
346  // on wxGTK we can not create the OpenGL context with a hidden window
347  // therefore we need to create the overview window open and later hide it
348  overview_hidden=false;
349 #endif
350  m_GLOverview->SetActive(!overview_hidden);
351 
352  // set the AUI manager to our panel
354  m_mgr->SetManagedWindow(vis_panel);
355  vis_panel->SetMinSize(wxSize(200,150));
356 
357  //create the sizer for the preview
358  wxFlexGridSizer * flexSizer = new wxFlexGridSizer(2,0,5,5);
359  flexSizer->AddGrowableCol(0);
360  flexSizer->AddGrowableRow(0);
361 
362  //overview sizer
363  wxBoxSizer * overview_sizer = new wxBoxSizer(wxVERTICAL);
364 
365 
366  flexSizer->Add(m_GLPreview,
367  1, // not vertically stretchable
368  wxEXPAND | // horizontally stretchable
369  wxALL, // draw border all around
370  5); // border width
371 
372  m_VFOVSlider = new wxSlider(preview_panel, -1, 1,
373  1, 180,
374  wxDefaultPosition, wxDefaultSize,
375  wxSL_VERTICAL | wxSL_AUTOTICKS,
376  wxDefaultValidator,
377  _("VFOV"));
378  m_VFOVSlider->SetLineSize(1);
379  m_VFOVSlider->SetPageSize(10);
380  m_VFOVSlider->SetTickFreq(5);
381  m_VFOVSlider->SetToolTip(_("drag to change the vertical field of view"));
382  m_VFOVSlider->Bind(wxEVT_SCROLL_CHANGED, [this](wxScrollEvent& e) {
384  opt.setVFOV(e.GetInt());
386  }
387  );
388 #ifdef __WXMAC__
389  m_VFOVSlider->Bind(wxEVT_SCROLL_THUMBRELEASE, [this](wxScrollEvent& e) {
391  opt.setVFOV(e.GetInt());
393  }
394  );
395 #endif
396  m_VFOVSlider->Bind(wxEVT_SCROLL_THUMBTRACK, [this](wxScrollEvent& e) {
398  opt.setVFOV(e.GetInt());
399  // we only actually update the panorama fully when the mouse is released.
400  // As we are dragging it we don't want to create undo events, but we would
401  // like to update the display, so we change the GLViewer's ViewState and
402  // request a redraw.
404  m_GLPreview->Refresh();
405  }
406  );
407 
408  flexSizer->Add(m_VFOVSlider, 0, wxEXPAND);
409 
410  m_HFOVSlider = new wxSlider(preview_panel, -1, 1,
411  1, 360,
412  wxDefaultPosition, wxDefaultSize,
413  wxSL_HORIZONTAL | wxSL_AUTOTICKS,
414  wxDefaultValidator,
415  _("HFOV"));
416  m_HFOVSlider->SetPageSize(10);
417  m_HFOVSlider->SetLineSize(1);
418  m_HFOVSlider->SetTickFreq(5);
419 
420  m_HFOVSlider->SetToolTip(_("drag to change the horizontal field of view"));
421  m_HFOVSlider->Bind(wxEVT_SCROLL_CHANGED, [this](wxScrollEvent& e) {
423  opt.setHFOV(e.GetInt());
425  }
426  );
427 #ifdef __WXMAC__
428  m_HFOVSlider->Bind(wxEVT_SCROLL_THUMBRELEASE, [this](wxScrollEvent& e) {
430  opt.setHFOV(e.GetInt());
432  }
433  );
434 #endif
435  m_HFOVSlider->Bind(wxEVT_SCROLL_THUMBTRACK, [this](wxScrollEvent& e) {
437  opt.setHFOV(e.GetInt());
438  // we only actually update the panorama fully when the mouse is released.
439  // As we are dragging it we don't want to create undo events, but we would
440  // like to update the display, so we change the GLViewer's ViewState and
441  // request a redraw.
443  m_GLPreview->Refresh();
444  }
445  );
446 
447  m_HFOVText = XRCCTRL(*this, "pano_text_hfov" ,wxTextCtrl);
449  m_HFOVText->PushEventHandler(new TextKillFocusHandler(this));
450  m_HFOVText->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnHFOVChanged, this);
451  m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
453  m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
454  m_VFOVText->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnVFOVChanged, this);
455 
456  m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
458  m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
459  m_ROILeftTxt->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnROIChanged, this);
460 
461  m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
463  m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
464  m_ROIRightTxt->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnROIChanged, this);
465 
466  m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
468  m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
469  m_ROITopTxt->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnROIChanged, this);
470 
471  m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
473  m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(this));
474  m_ROIBottomTxt->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnROIChanged, this);
475 
476  m_GuideChoiceCrop = XRCCTRL(*this, "preview_guide_choice_crop", wxChoice);
477  m_GuideChoiceProj = XRCCTRL(*this, "preview_guide_choice_proj", wxChoice);
478  m_GuideChoiceDrag = XRCCTRL(*this, "preview_guide_choice_drag", wxChoice);
479  int guide=cfg->Read(wxT("/GLPreviewFrame/guide"),0l);
480  m_GuideChoiceCrop->SetSelection(guide);
481  m_GuideChoiceProj->SetSelection(guide);
482  m_GuideChoiceDrag->SetSelection(guide);
483  m_GuideChoiceCrop->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnGuideChanged, this);
484  m_GuideChoiceProj->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnGuideChanged, this);
485  m_GuideChoiceDrag->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnGuideChanged, this);
486 
487  flexSizer->Add(m_HFOVSlider, 0, wxEXPAND);
488 
489  m_overviewCommandPanel = wxXmlResource::Get()->LoadPanel(overview_panel,wxT("overview_command_panel"));
490  m_OverviewModeChoice = XRCCTRL(*this, "overview_mode_choice", wxChoice);
492  const wxSize dpiSize(m_overviewCommandPanel->FromDIP(wxSize(200, 20)));
493  m_overviewCommandPanel->SetSize(0, 0, dpiSize.GetWidth(), dpiSize.GetHeight(), wxSIZE_AUTO_WIDTH);
494 
495  overview_sizer->Add(m_overviewCommandPanel, 0, wxEXPAND);
496  overview_sizer->Add(m_GLOverview, 1, wxEXPAND);
497 
498  bool showGrid;
499  cfg->Read(wxT("/GLPreviewFrame/showPreviewGrid"),&showGrid,true);
500  GetMenuBar()->FindItem(XRCID("action_show_grid"))->Check(showGrid);
501 
502  preview_panel->SetSizer(flexSizer);
503  overview_panel->SetSizer(overview_sizer);
504 
505  m_mgr->AddPane(preview_panel,
506  wxAuiPaneInfo(
507  ).Name(wxT("preview")
508  ).MinSize(300,200
509  ).CloseButton(false
510  ).CaptionVisible(false
511  ).Caption(_("Preview")
512  ).Floatable(false
513  ).Dockable(false
514  ).Center(
515  )
516  );
517 
518  m_mgr->AddPane(overview_panel,
519  wxAuiPaneInfo(
520  ).Name(wxT("overview")
521  ).MinSize(300,200
522  ).CloseButton(false
523  ).CaptionVisible(
524  ).Caption(_("Overview")
525  ).FloatingSize(100,100
526  ).FloatingPosition(500,500
527  ).Dockable(true
528  ).PinButton(
529  ).Left(
530  ).Show(!overview_hidden
531  )
532  );
533 
534 
535  m_topsizer->Add(vis_panel, 1, wxEXPAND);
536 
537  //assistant related controls
538  m_loadImagesButton = XRCCTRL(*this, "ass_load_images_button", SplitButton);
540  m_loadImagesButton->GetSplitButtonMenu()->Append(ID_ASS_LOAD_IMAGES, _("Load images (autodetect lens type)..."));
541  // event handler for main button
542  m_loadImagesButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnLoadImages, this);
543  // event handler for first menu item with automatic lens type detection
544  Bind(wxEVT_MENU, &GLPreviewFrame::OnLoadImages, this, ID_ASS_LOAD_IMAGES);
545  m_loadImagesButton->GetSplitButtonMenu()->AppendSeparator();
546  // now add all lens types to menu
548  int lensTypeId = ID_ASS_LOAD_IMAGES + 1;
549  for (auto& lensType : lensInfoVector)
550  {
551  m_loadImagesButton->GetSplitButtonMenu()->Append(lensTypeId, wxString::Format(_("Load images (lens type: %s)..."), lensType.name));
552  const int lensId = lensType.id;
553  Bind(wxEVT_MENU, [this, lensId](wxCommandEvent&) { LoadImages(lensId); }, lensTypeId);
554  ++lensTypeId;
555  };
556 
557  m_alignButton = XRCCTRL(*this, "ass_align_button", SplitButton);
559  m_alignButton->Disable();
560  // add default assistant to drop down menu
561  m_alignButton->GetSplitButtonMenu()->Append(ID_ASSISTANT_MENU, _("Panorama assistant (default)"), m_alignButton->GetToolTipText());
562  // event handler for main button
563  m_alignButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnAlign, this);
564  // event handler for first menu item - default align
565  Bind(wxEVT_MENU, &GLPreviewFrame::OnAlign, this, ID_ASSISTANT_MENU);
566  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
567  // provide help texts in the status bar, add the necessary event handlers
568  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
569  m_alignButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
570  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_alignButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
571  );
572 
573  m_createButton = XRCCTRL(*this, "ass_create_button", SplitButton);
575  m_createButton->Disable();
576  // add default create function to drop down menu
577  m_createButton->GetSplitButtonMenu()->Append(ID_CREATEPANO_MENU, _("Stitch normal panorama (default)"), m_createButton->GetToolTipText());
578  // event handler for main button
579  m_createButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnCreate, this);
580  // event handler for first menu item
581  Bind(wxEVT_MENU, &GLPreviewFrame::OnCreate, this, ID_CREATEPANO_MENU);
582  m_createButton->GetSplitButtonMenu()->AppendSeparator();
583  // provide help texts in the status bar, add the necessary event handlers
584  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { SetStatusText(wxString()); });
585  m_createButton->GetSplitButtonMenu()->Bind(wxEVT_MENU_HIGHLIGHT,
586  [this](wxMenuEvent& e) { if (e.GetId() > 0) SetStatusText(m_createButton->GetSplitButtonMenu()->GetHelpString(e.GetId())); }
587  );
588 
589  m_ProjectionChoice = XRCCTRL(*this,"projection_choice",wxChoice);
590 
591  /* populate with all available projection types */
592  int nP = panoProjectionFormatCount();
593  for(int n=0; n < nP; n++) {
594  pano_projection_features proj;
595  if (panoProjectionFeaturesQuery(n, &proj)) {
596  wxString str2(proj.name, wxConvLocal);
597  m_ProjectionChoice->Append(wxGetTranslation(str2));
598  }
599  }
600  m_ProjectionChoice->SetSelection(2);
601  m_ProjectionChoice->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnProjectionChoice, this);
602 
604  // Blend mode
605  // remaining blend mode should be added after OpenGL context has been created
606  // see FillBlendMode()
607  m_differenceIndex = -1;
608  // create choice item
609  m_BlendModeChoice = XRCCTRL(*this,"blend_mode_choice",wxChoice);
610  m_BlendModeChoice->Append(_("normal"));
611  m_BlendModeChoice->SetSelection(0);
612  m_BlendModeChoice->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnBlendChoice, this);
613 
614  m_DragModeChoice = XRCCTRL(*this, "drag_mode_choice", wxChoice);
616  bool individualDrag;
617  cfg->Read(wxT("/GLPreviewFrame/individualDragMode"), &individualDrag, false);
618  if(individualDrag)
619  {
620  m_DragModeChoice->SetSelection(1);
621  }
622  else
623  {
624  m_DragModeChoice->SetSelection(0);
625  };
626  m_DragModeChoice->Bind(wxEVT_CHOICE, &GLPreviewFrame::OnDragChoice, this);
627  // default drag mode
629 
630  // TODO implement hdr display in OpenGL, if possible?
631  // Disabled until someone can figure out HDR display in OpenGL.
632  /*
634  // LDR, HDR
635  blendModeSizer->Add(new wxStaticText(this, -1, _("Output:")),
636  0, // not vertically strechable
637  wxALL | wxALIGN_CENTER_VERTICAL, // draw border all around
638  5); // border width
639 
640  m_choices[0] = _("LDR");
641  m_choices[1] = _("HDR");
642  m_outputModeChoice = new wxChoice(this, ID_OUTPUTMODE_CHOICE,
643  wxDefaultPosition, wxDefaultSize,
644  2, m_choices);
645  m_outputModeChoice->SetSelection(0);
646  blendModeSizer->Add(m_outputModeChoice,
647  0,
648  wxALL | wxALIGN_CENTER_VERTICAL,
649  5);
650  */
651 
653  // exposure
654  m_defaultExposureBut = XRCCTRL(*this, "exposure_default_button", wxBitmapButton);
655  m_defaultExposureBut->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnDefaultExposure, this);
656 
657  m_exposureTextCtrl = XRCCTRL(*this, "exposure_text", wxTextCtrl);
658  m_exposureTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
659  m_exposureTextCtrl->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnExposureChanged, this);
660 
661  m_exposureSpinBut = XRCCTRL(*this, "exposure_spin", wxSpinButton);
662  m_exposureSpinBut->SetValue(0);
663  m_exposureSpinBut->SetMaxSize(wxSize(-1, m_exposureTextCtrl->GetSize().GetHeight()));
664  m_exposureSpinBut->Bind(wxEVT_SPIN_DOWN, &GLPreviewFrame::OnDecreaseExposure, this);
665  m_exposureSpinBut->Bind(wxEVT_SPIN_UP, &GLPreviewFrame::OnIncreaseExposure, this);
666 
667  m_rangeCompressionTextCtrl = XRCCTRL(*this, "range_compression_text", wxTextCtrl);
668  m_rangeCompressionTextCtrl->PushEventHandler(new TextKillFocusHandler(this));
670 
671  m_rangeCompressionSpinBut = XRCCTRL(*this, "range_compression_spin", wxSpinButton);
672  m_rangeCompressionSpinBut->SetValue(0);
673  m_rangeCompressionSpinBut->SetMaxSize(wxSize(-1, m_rangeCompressionTextCtrl->GetSize().GetHeight()));
676 
677  m_projection_panel = XRCCTRL(*this, "projection_panel", wxPanel);
678  m_projParamSizer = new wxBoxSizer(wxHORIZONTAL);
679 
680  wxBitmapButton * resetProjButton=new wxBitmapButton(m_projection_panel, PROJ_PARAM_RESET_ID,
681  wxArtProvider::GetBitmap(wxART_REDO));
682  resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
683  resetProjButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnProjParameterReset, this);
684  m_projParamSizer->Add(resetProjButton, 0, wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL, 5);
685 
686  m_projParamNamesLabel.resize(PANO_PROJECTION_MAX_PARMS);
687  m_projParamTextCtrl.resize(PANO_PROJECTION_MAX_PARMS);
688  m_projParamSlider.resize(PANO_PROJECTION_MAX_PARMS);
689 
690  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
691 
692  wxBoxSizer* paramBoxSizer = new wxBoxSizer(wxVERTICAL);
693  m_projParamNamesLabel[i] = new wxStaticText(m_projection_panel, PROJ_PARAM_NAMES_ID+i, _("param:"));
694  paramBoxSizer->Add(m_projParamNamesLabel[i],
695  0, // not vertically strechable
696  wxLEFT | wxRIGHT, // draw border all around
697  5); // border width
698  m_projParamTextCtrl[i] = new wxTextCtrl(m_projection_panel, PROJ_PARAM_VAL_ID+i, wxT("0"),
699  wxDefaultPosition, wxSize(35,-1), wxTE_PROCESS_ENTER);
700  m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
701  m_projParamTextCtrl[i]->Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnProjParameterChanged, this);
702  paramBoxSizer->Add(m_projParamTextCtrl[i],
703  0, // not vertically strechable
704  wxLEFT | wxRIGHT, // draw border all around
705  5); // border width
706 
707  m_projParamSizer->Add(paramBoxSizer);
708  m_projParamSlider[i] = new wxSlider(m_projection_panel, PROJ_PARAM_SLIDER_ID+i, 0, -90, 90);
709  m_projParamSlider[i]->Bind(wxEVT_SCROLL_CHANGED, &GLPreviewFrame::OnChangeProjectionParam, this);
710 #ifdef __WXMAC__
711  m_projParamSlider[i]->Bind(wxEVT_SCROLL_THUMBRELEASE, &GLPreviewFrame::OnChangeProjectionParam, this);
712 #endif
713  m_projParamSlider[i]->Bind(wxEVT_SCROLL_THUMBTRACK, &GLPreviewFrame::OnTrackChangeProjectionParam, this);
714 
716  1, // not vertically strechable
717  wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL , // draw border all around
718  5); // border width
719  }
720 
721  m_projection_panel->GetSizer()->Add(m_projParamSizer, 1, wxALIGN_CENTER_VERTICAL);
722 
723  // do not show projection param sizer
724  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
725 
726  // the initial size as calculated by the sizers
727  this->SetSizer( m_topsizer );
728  m_topsizer->SetSizeHints( this );
729 
730  // set the minimize icon
731 #ifdef __WXMSW__
732  wxIconBundle myIcons(huginApp::Get()->GetXRCPath() + wxT("data/hugin.ico"),wxBITMAP_TYPE_ICO);
733  SetIcons(myIcons);
734 #else
735  wxIcon myIcon(huginApp::Get()->GetXRCPath() + wxT("data/hugin.png"),wxBITMAP_TYPE_PNG);
736  SetIcon(myIcon);
737 #endif
738 
739  m_pano.addObserver(this);
740 
741  RestoreFramePosition(this, wxT("GLPreviewFrame"));
742 
743 #ifdef __WXMSW__
744  // wxFrame does have a strange background color on Windows..
745  this->SetBackgroundColour(m_GLPreview->GetBackgroundColour());
746 #endif
747 
748  m_showProjectionHints = cfg->Read(wxT("/GLPreviewFrame/ShowProjectionHints"), HUGIN_SHOW_PROJECTION_HINTS) == 1;
749  m_degDigits = wxConfigBase::Get()->Read(wxT("/General/DegreeFractionalDigitsEdit"),3);
750 
751  // tell the manager to "commit" all the changes just made
752  m_mgr->Update();
753 
754  // bind event handlers
755  Bind(wxEVT_CLOSE_WINDOW, &GLPreviewFrame::OnClose, this);
756  Bind(wxEVT_SHOW, &GLPreviewFrame::OnShowEvent, this);
757  Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { m_GLPreview->Refresh(); e.Skip();});
758  Bind(wxEVT_SLIDER, &GLPreviewFrame::OnLayoutScaleChange, this, XRCID("layout_scale_slider"));
759  Bind(wxEVT_COLOURPICKER_CHANGED, &GLPreviewFrame::OnPreviewBackgroundColorChanged, this, XRCID("preview_background"));
760  // handler for menu items
761  Bind(wxEVT_MENU, &GLPreviewFrame::OnOverviewToggle, this, XRCID("action_show_overview"));
762  Bind(wxEVT_MENU, &GLPreviewFrame::OnSwitchPreviewGrid, this, XRCID("action_show_grid"));
763  Bind(wxEVT_MENU, &GLPreviewFrame::OnFullScreen, this, XRCID("ID_SHOW_FULL_SCREEN_PREVIEW"));
764  Bind(wxEVT_MENU, &GLPreviewFrame::OnShowMainFrame, this, XRCID("action_show_main_frame"));
765  Bind(wxEVT_MENU, &GLPreviewFrame::OnUserExit, this, XRCID("action_exit_preview"));
766  // context menu of select all button
767  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectAllMenu, this, XRCID("selectMenu_selectAll"));
768  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectMedianMenu, this, XRCID("selectMenu_selectMedian"));
769  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectDarkestMenu, this, XRCID("selectMenu_selectBrightest"));
770  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectBrightestMenu, this, XRCID("selectMenu_selectDarkest"));
771  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectKeepSelection, this, XRCID("selectMenu_keepCurrentSelection"));
772  Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectResetSelection, this, XRCID("selectMenu_resetSelection"));
773  // handler for different buttons
774  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnCenterHorizontally, this, XRCID("preview_center_tool"));
775  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnFitPano, this, XRCID("preview_fit_pano_tool"));
776  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnFitPano, this, XRCID("preview_fit_pano_tool2"));
777  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnStraighten, this, XRCID("preview_straighten_pano_tool"));
778  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnNumTransform, this, XRCID("apply_num_transform"));
779  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnAutocrop, this, XRCID("preview_autocrop_tool"));
780  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnStackAutocrop, this, XRCID("preview_stack_autocrop_tool"));
781  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnAutocropOutside, this, XRCID("preview_autocrop_outside_tool"));
782  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnResetCrop, this, XRCID("reset_crop_button"));
783  Bind(wxEVT_BUTTON, &GLPreviewFrame::OnSetCropAspect, this, XRCID("crop_aspect_button"));
784  //checkboxes
785  Bind(wxEVT_CHECKBOX, &GLPreviewFrame::OnPhotometric, this, XRCID("preview_photometric_tool"));
786  Bind(wxEVT_CHECKBOX, &GLPreviewFrame::OnControlPoint, this, XRCID("preview_control_point_tool"));
787  // process enter key in num transform boxes
788  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_yaw"));
789  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_pitch"));
790  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_roll"));
791  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_x"));
792  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_y"));
793  Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_z"));
794 
795  if (cfg->Read(wxT("/GLPreviewFrame/isShown"), 0l) != 0)
796  {
797 #if defined __WXMSW__ || defined __WXMAC__
798  InitPreviews();
799  Show();
800 #else
801  Show();
803 #endif
804  }
805  SetDropTarget(new PanoDropTarget(m_pano, true));
806 #if defined __WXMAC__
807  Layout();
808  Update();
809 #endif
810 }
811 
813 {
814 #ifdef __WXGTK__
815  if(loadedLayout)
816  {
817  return;
818  };
819  loadedLayout=true;
820 #endif
821  wxString OpenGLLayout=wxConfig::Get()->Read(wxT("/GLPreviewFrame/OpenGLLayout"));
822  if(!OpenGLLayout.IsEmpty())
823  {
824  m_mgr->LoadPerspective(OpenGLLayout,true);
825 #ifdef __WXGTK__
826  if(!GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked())
827  {
828  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
829  if (inf.IsOk())
830  {
831  inf.Hide();
832  }
833  m_GLOverview->SetActive(false);
834  };
835  m_mgr->Update();
836  wxShowEvent dummy;
837  dummy.SetShow(true);
838  OnShowEvent(dummy);
839 #endif
840  };
841  FillBlendChoice();
842 };
843 
845 {
846  wxConfigBase * cfg = wxConfigBase::Get();
847 
848  StoreFramePosition(this, wxT("GLPreviewFrame"));
849 
850  if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
851  cfg->Write(wxT("/GLPreviewFrame/isShown"), 1l);
852  } else {
853  cfg->Write(wxT("/GLPreviewFrame/isShown"), 0l);
854  }
855 
856  cfg->Write(wxT("/GLPreviewFrame/blendMode"), m_BlendModeChoice->GetSelection());
857  cfg->Write(wxT("/GLPreviewFrame/OpenGLLayout"), m_mgr->SavePerspective());
858  cfg->Write(wxT("/GLPreviewFrame/overview_hidden"), !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
859  cfg->Write(wxT("/GLPreviewFrame/showPreviewGrid"), GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
860  cfg->Write(wxT("/GLPreviewFrame/individualDragMode"), individualDragging());
861  cfg->Write(wxT("/GLPreviewFrame/guide"),m_GuideChoiceProj->GetSelection());
862 };
863 
865 {
866  DEBUG_TRACE("dtor writing config");
868 
869  // delete all of the tools. When the preview is never used we never get an
870  // OpenGL context and therefore don't create the tools.
871  if (crop_tool)
872  {
884  }
895  }
903  }
904  m_exposureTextCtrl->PopEventHandler(true);
905  m_HFOVText->PopEventHandler(true);
906  m_rangeCompressionTextCtrl->PopEventHandler(true);
907  m_VFOVText->PopEventHandler(true);
908  m_ROILeftTxt->PopEventHandler(true);
909  m_ROIRightTxt->PopEventHandler(true);
910  m_ROITopTxt->PopEventHandler(true);
911  m_ROIBottomTxt->PopEventHandler(true);
912  for (int i=0; i < m_ToggleButtons.size(); i++)
913  {
914  m_ToggleButtons[i]->PopEventHandler(true);
915  m_GroupToggleButtons[i]->PopEventHandler(true);
916  }
917  for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
918  {
919  m_projParamTextCtrl[i]->PopEventHandler(true);
920  };
921  m_pano.removeObserver(this);
922 
923  // deinitialize the frame manager
924  m_mgr->UnInit();
925  if (m_mgr) {
926  delete m_mgr;
927  }
929  {
930  delete m_filemenuSimple;
931  }
932  else
933  {
934  delete m_filemenuAdvanced;
935  };
936 
937  DEBUG_TRACE("dtor end");
938 }
939 
941 {
943  {
947  };
948 };
949 
954 {
955  if (m_BlendModeChoice != NULL)
956  {
957  int index=m_BlendModeChoice->GetSelection();
958  if(index==0)
959  {
960  // normal mode
961  if (preview_helper != NULL
962  && difference_tool != NULL)
963  {
965  };
966 
967  if (panosphere_overview_helper != NULL
968  && panosphere_difference_tool != NULL)
969  {
971  };
972 
973  if (plane_overview_helper != NULL
974  && plane_difference_tool != NULL)
975  {
977  };
978 
979 
980  }
981  else
982  {
983  if(index==m_differenceIndex)
984  {
985  // difference mode
986  if (preview_helper != NULL
987  && identify_tool != NULL
988  && difference_tool != NULL )
989  {
991 // preview_helper->DeactivateTool(identify_tool);
992  m_identify_togglebutton->SetValue(false);
995  };
996 
997  // difference mode
998  if (panosphere_overview_helper != NULL
1000  && panosphere_difference_tool != NULL)
1001  {
1002 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
1005  };
1006 
1007  // difference mode
1008  if (plane_overview_helper != NULL
1009  && plane_overview_identify_tool != NULL
1010  && plane_difference_tool != NULL)
1011  {
1012 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
1015  };
1016 
1017  }
1018  else
1019  {
1020  DEBUG_WARN("Unknown blend mode selected");
1021  };
1022  }
1023  }
1024 }
1025 
1027 {
1028  m_ROILeftTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().left() ));
1029  m_ROIRightTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().right() ));
1030  m_ROITopTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().top() ));
1031  m_ROIBottomTxt->ChangeValue(wxString::Format(wxT("%d"), opts.getROI().bottom() ));
1032 
1033  // display the current aspect ratio
1034  if (opts.getROI().area() > 0)
1035  {
1036  const int commonDivisor = hugin_utils::gcd(opts.getROI().width(), opts.getROI().height());
1037  wxString labelAspectRatio;
1038  if (commonDivisor > std::pow(10, hugin_utils::floori(log10f(std::max(opts.getROI().width(), opts.getROI().height()))) - 2))
1039  {
1040  labelAspectRatio = wxString::Format("%d:%d", opts.getROI().width() / commonDivisor, opts.getROI().height() / commonDivisor);
1041  }
1042  else
1043  {
1044  const float ratio = 1.0f * opts.getROI().width() / opts.getROI().height();
1045  if (ratio > 1.0f)
1046  {
1047  labelAspectRatio=wxString::Format("%.2f:1", ratio);
1048  }
1049  else
1050  {
1051  labelAspectRatio=wxString::Format("1:%.2f", 1.0f / ratio);
1052  };
1053  };
1054  XRCCTRL(*this, "crop_aspect_label", wxStaticText)->SetLabel(labelAspectRatio);
1055  };
1056 
1057 };
1058 
1060 {
1061  m_alignButton->Enable(pano.getNrOfImages()>0);
1062 
1063  if(pano.getNrOfImages()==0)
1064  {
1065  m_createButton->Disable();
1066  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("No images loaded."));
1067  }
1068  else
1069  {
1070  bool enableCreate = false;
1071  // check if images are at position 0
1072  for (size_t i = 0; i < pano.getNrOfImages(); ++i)
1073  {
1074  const HuginBase::SrcPanoImage& img = pano.getImage(i);
1075  if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
1076  {
1077  enableCreate = true;
1078  break;
1079  };
1080  };
1081  // disable create button after loading images
1082  const std::string lastCmd = PanoCommand::GlobalCmdHist::getInstance().getLastCommandName();
1083  if (lastCmd == "add images" || lastCmd == "add and distribute images")
1084  {
1085  enableCreate = false;
1086  };
1087  if (!enableCreate && pano.getNrOfImages() == 1)
1088  {
1089  // some more checks for single image projects
1091  {
1092  enableCreate = true;
1093  };
1094  if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
1095  {
1096  enableCreate = true;
1097  };
1098  if (pano.getImage(0).getProjection() == HuginBase::SrcPanoImage::EQUIRECTANGULAR)
1099  {
1100  enableCreate = true;
1101  };
1102  };
1103  m_createButton->Enable(enableCreate);
1104  }
1105 
1106  if (pano.getNrOfImages() > 1)
1107  {
1108  // in wxWidgets 2.9, format must have types that exactly match.
1109  // However std::size_t could be any unsiged integer, so we cast it to
1110  // unsigned long.int to be on the safe side.
1111  wxString alignMsg = wxString::Format(_("%lu images are connected by %lu control points.\n"), (unsigned long int) pano.getNrOfImages(), (unsigned long int) pano.getCtrlPoints().size());
1112 
1113  if (m_pano.getNrOfCtrlPoints() > 0)
1114  {
1115  // find components..
1117  const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
1118  if (comps.size() > 1)
1119  {
1120  alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
1121  }
1122  else
1123  {
1124  if (m_pano.needsOptimization())
1125  {
1126  alignMsg += _("Images or control points have changed, new alignment is needed.");
1127  }
1128  else
1129  {
1130  HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages(), MainFrame::Get()->GetOptimizeIgnoreLineCp());
1131  calcStats.run();
1132  const double max = calcStats.getResultMax();
1133  const double mean = calcStats.getResultMean();
1134 
1135  if (max != 0.0)
1136  {
1137  alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max);
1138  }
1139  }
1140  }
1141  }
1142  wxStaticText* statusCtrl = XRCCTRL(*this, "ass_status_text", wxStaticText);
1143  statusCtrl->SetLabel(alignMsg);
1144  statusCtrl->InvalidateBestSize();
1145  m_tool_notebook->GetPage(0)->Layout();
1146  Refresh();
1147  }
1148  else
1149  {
1150  if (pano.getNrOfImages() == 1)
1151  {
1152  XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("One image loaded."));
1153  };
1154  };
1155 
1156  GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
1157  GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
1158 
1159  // TODO: update meaningful help text and dynamic links to relevant tabs
1160 
1161  const HuginBase::PanoramaOptions & opts = pano.getOptions();
1162 
1163  wxString projection;
1164  m_ProjectionChoice->SetSelection(opts.getProjection());
1165  m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
1166 
1167  // No HDR display yet.
1168  /*
1169  m_outputModeChoice->SetSelection(opts.outputMode);
1170  if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
1171  m_exposureTextCtrl->Hide();
1172  m_defaultExposureBut->Hide();
1173  m_decExposureBut->Hide();
1174  m_incExposureBut->Hide();
1175  } else {
1176  m_exposureTextCtrl->Show();
1177  m_defaultExposureBut->Show();
1178  m_decExposureBut->Show();
1179  m_incExposureBut->Show();
1180  }*/
1181  m_exposureTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputExposureValue,2).c_str(), wxConvLocal));
1182  m_rangeCompressionTextCtrl->ChangeValue(wxString(hugin_utils::doubleToString(opts.outputRangeCompression, 1).c_str(), wxConvLocal));
1183 
1184  const bool activeImgs = !pano.getActiveImages().empty();
1185 
1186  // TODO: enable display of parameters and set their limits, if projection has some.
1187 
1188  int nParam = opts.m_projFeatures.numberOfParameters;
1189  bool relayout = false;
1190  // if the projection format has changed
1191  if (opts.getProjection() != m_oldProjFormat) {
1192  DEBUG_DEBUG("Projection format changed");
1193  if (nParam) {
1194  // show parameters and update labels.
1195  m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
1196  int i;
1197  for (i=0; i < nParam; i++) {
1198  const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
1199  wxString str2(pp->name, wxConvLocal);
1200  str2 = wxGetTranslation(str2);
1201  m_projParamNamesLabel[i]->SetLabel(str2);
1202  m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
1203  }
1204  for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
1205  m_projParamNamesLabel[i]->Hide();
1206  m_projParamSlider[i]->Hide();
1207  m_projParamTextCtrl[i]->Hide();
1208  }
1209  relayout = true;
1210  } else {
1211  m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
1212  relayout = true;
1213  }
1214  }
1215  if (nParam) {
1216  // display new values
1217  std::vector<double> params = opts.getProjectionParameters();
1218  assert((int) params.size() == nParam);
1219  for (int i=0; i < nParam; i++) {
1220  wxString val = wxString(hugin_utils::doubleToString(params[i],1).c_str(), wxConvLocal);
1221  m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
1222  m_projParamSlider[i]->SetValue(hugin_utils::roundi(params[i]));
1223  }
1224  }
1225  if (relayout) {
1226  m_projection_panel->Layout();
1227  Refresh();
1228  }
1229  SetStatusText(wxString::Format(wxT("%.1f x %.1f"), opts.getHFOV(), opts.getVFOV()),2);
1230  m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
1231  m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
1232  std::string val;
1233  val = hugin_utils::doubleToString(opts.getHFOV(),1);
1234  m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1235  val = hugin_utils::doubleToString(opts.getVFOV(),1);
1236  m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1237  m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
1238 
1239  m_oldProjFormat = opts.getProjection();
1240 
1241  XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
1242  XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
1243  UpdateRoiDisplay(opts);
1244 
1246  {
1248  };
1249  redrawPreview();
1250 }
1251 
1253 {
1254  DEBUG_TRACE("");
1255 
1256  bool dirty = false;
1257 
1258  unsigned int nrImages = pano.getNrOfImages();
1259  unsigned int nrButtons = m_ToggleButtons.size();
1260 
1261  GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
1262 
1263 // m_displayedImgs.clear();
1264 
1265  // remove items for nonexisting images
1266  for (int i=nrButtons-1; i>=(int)nrImages; i--)
1267  {
1268  m_ButtonSizer->Detach(m_ToggleButtonPanel[i]);
1269  // Image toggle buttons have a event handler on the stack which
1270  // must be removed before the buttons get destroyed.
1271  m_ToggleButtons[i]->PopEventHandler();
1272  m_GroupToggleButtons[i]->PopEventHandler();
1273  delete m_ToggleButtons[i];
1274  delete m_GroupToggleButtons[i];
1275  delete m_ToggleButtonPanel[i];
1276  m_ToggleButtons.pop_back();
1277  m_GroupToggleButtons.pop_back();
1278  m_ToggleButtonPanel.pop_back();
1279  delete toogle_button_event_handlers[i];
1280  toogle_button_event_handlers.pop_back();
1283  dirty = true;
1284  }
1285 
1286  //change overview mode to panosphere if the translation plane parameter are non zero
1288  {
1290  {
1292  m_OverviewModeChoice->SetSelection(0);
1293  //check if drag mode is mosaic, if so reset to normal
1294  if(drag_tool)
1295  {
1297  {
1298  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
1301  // adjust the layout
1302  DragChoiceLayout(m_DragModeChoice->GetSelection());
1303  };
1304  };
1305  }
1306  }
1307 
1308  // add buttons
1309  if ( nrImages >= nrButtons ) {
1310  for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
1311  if (*it >= nrButtons) {
1312  // create new item.
1313 // wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
1314  //put wxToggleButton in a wxPanel because
1315  //on Windows the background colour of wxToggleButton can't be changed
1316  wxPanel *pan = new wxPanel(m_ButtonPanel);
1317  wxBoxSizer * siz = new wxBoxSizer(wxVERTICAL);
1318  pan->SetSizer(siz);
1319  wxToggleButton * but = new wxToggleButton(pan,
1320  ID_TOGGLE_BUT + *it,
1321  wxString::Format(wxT(" %d "),*it),
1322  wxDefaultPosition, wxDefaultSize,
1323  wxBU_EXACTFIT);
1324 
1325  wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxT(""));
1326 
1327 #if defined __WXMSW__ || defined __WXMAC__
1328  //we need a border around the button to see the colored panel
1329  //because changing backgroundcolor of wxToggleButton does not work in wxMSW
1330  siz->AddSpacer(5);
1331  siz->Add(butcheck, 0, wxALIGN_CENTRE_HORIZONTAL | wxFIXED_MINSIZE, 0);
1332  siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
1333 #else
1334  siz->Add(but,0,wxALL ,0);
1335  siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
1336 #endif
1337  // for the identification tool to work, we need to find when the
1338  // mouse enters and exits the button. We use a custom event
1339  // handler, which will also toggle the images:
1341  event_handler->AddIdentifyTool(&identify_tool);
1344  toogle_button_event_handlers.push_back(event_handler);
1345  but->PushEventHandler(event_handler);
1346 
1347  ImageGroupButtonEventHandler * group_event_handler = new
1348  ImageGroupButtonEventHandler(*it, this, &m_pano);
1349  group_event_handler->AddDragTool((DragTool**) &drag_tool);
1350  group_event_handler->AddDragTool((DragTool**) &overview_drag_tool);
1351  group_event_handler->AddIdentifyTool(&identify_tool);
1352  group_event_handler->AddIdentifyTool(&panosphere_overview_identify_tool);
1353  group_event_handler->AddIdentifyTool(&plane_overview_identify_tool);
1354  toggle_group_button_event_handlers.push_back(group_event_handler);
1355  butcheck->PushEventHandler(group_event_handler);
1356  butcheck->Show(individualDragging() && m_mode==mode_drag);
1357 
1358  but->SetValue(true);
1359  m_ButtonSizer->Add(pan,
1360  0,
1361  wxLEFT | wxTOP,
1362  0);
1363  m_ToggleButtons.push_back(but);
1364  m_GroupToggleButtons.push_back(butcheck);
1365  m_ToggleButtonPanel.push_back(pan);
1366  dirty = true;
1367  }
1368  }
1369  }
1370 
1371  // update existing items
1372  HuginBase::UIntSet displayedImages = m_pano.getActiveImages();
1373  for (unsigned i=0; i < nrImages; i++) {
1374  m_ToggleButtons[i]->SetValue(set_contains(displayedImages, i));
1375  wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
1376  m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
1377  }
1378 
1379  if (dirty) {
1380  m_ButtonSizer->FitInside(m_ButtonPanel);
1381  Layout();
1382  SendSizeEvent();
1383  DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
1384  DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
1385  }
1386  if(nrImages==0)
1387  {
1389  m_tool_notebook->ChangeSelection(mode_assistant);
1390  };
1391  for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
1392  {
1393  m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
1394  };
1395  redrawPreview();
1396 }
1397 
1399 {
1400  m_GLPreview->Refresh();
1401  m_GLOverview->Refresh();
1402 }
1403 
1405 {
1406  if (preview_helper)
1407  {
1409  m_GLPreview->Redraw();
1410  };
1411 }
1412 
1413 void GLPreviewFrame::OnShowEvent(wxShowEvent& e)
1414 {
1415 
1416  DEBUG_TRACE("OnShow");
1417  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1418  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1419  if (inf.IsOk()) {
1420  if (e.IsShown()) {
1421  if (!inf.IsShown() && toggle_on ) {
1422  inf.Show();
1423  m_mgr->Update();
1424  }
1425  } else {
1426  if (inf.IsFloating() && inf.IsShown()) {
1427  DEBUG_DEBUG("hiding overview float");
1428  inf.Hide();
1429  m_mgr->Update();
1430  }
1431  }
1432  }
1433 
1434 }
1435 
1436 //the following methods are to substitude the GLViewer KeyUp and KeyDown methods
1437 //so that tools use key events that happen globally to the preview frame
1438 //however only key up event is sent, and not key down
1439 //so until this is resolved they will remain to be handled by GLViewer
1440 void GLPreviewFrame::KeyDown(wxKeyEvent& e)
1441 {
1442  if (preview_helper) {
1443  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1444  }
1445  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1447  if (plane_overview_helper) {
1448  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1449  }
1452  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1453  }
1454  }
1455 
1456  }
1457  e.Skip();
1458 }
1459 
1460 void GLPreviewFrame::KeyUp(wxKeyEvent& e)
1461 {
1462  if (preview_helper) {
1463  preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1464  }
1465  if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1467  if (plane_overview_helper) {
1468  plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1469  }
1470  }
1473  panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1474  }
1475  }
1476 
1477  }
1478  e.Skip();
1479 }
1480 
1481 
1482 
1483 void GLPreviewFrame::OnOverviewToggle(wxCommandEvent& e)
1484 {
1485  DEBUG_TRACE("overview toggle");
1486  bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1487  wxAuiPaneInfo &inf = m_mgr->GetPane(wxT("overview"));
1488  if (inf.IsOk()) {
1489  if (inf.IsShown() && !toggle_on) {
1490  inf.Hide();
1491  m_GLOverview->SetActive(false);
1492  m_mgr->Update();
1493  } else if (!(inf.IsShown() && toggle_on)) {
1494  inf.Show();
1495 #if defined __WXMSW__ || defined __WXMAC__
1496  m_GLOverview->SetActive(true);
1497  m_mgr->Update();
1498 #else
1499  m_mgr->Update();
1500  m_GLOverview->SetActive(true);
1501 #endif
1502  }
1503  }
1504 }
1505 
1506 void GLPreviewFrame::OnSwitchPreviewGrid(wxCommandEvent & e)
1507 {
1508  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
1509  {
1512  }
1513  else
1514  {
1517  }
1518  m_GLPreview->Refresh();
1519  m_GLOverview->Refresh();
1520 }
1521 
1522 void GLPreviewFrame::OnClose(wxCloseEvent& event)
1523 {
1524  DEBUG_TRACE("OnClose")
1525  // do not close, just hide if we're not forced
1526  if(m_guiLevel==GUI_SIMPLE)
1527  {
1528  if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
1529  {
1530  if (event.CanVeto())
1531  {
1532  event.Veto();
1533  return;
1534  };
1535  };
1536  MainFrame::Get()->Close(true);
1537  }
1538  else
1539  {
1540  if (event.CanVeto())
1541  {
1542  event.Veto();
1543  Hide();
1544  DEBUG_DEBUG("hiding");
1545  }
1546  else
1547  {
1548  DEBUG_DEBUG("closing");
1549  this->Destroy();
1550  }
1551  };
1552 }
1553 
1554 #if 0
1555 // need to add the wxChoice somewhere
1556 void PreviewFrame::OnProjectionChanged()
1557 {
1558  PanoramaOptions opt = m_pano.getOptions();
1559  int lt = m_ProjectionChoice->GetSelection();
1560  wxString Ip;
1561  switch ( lt ) {
1562  case PanoramaOptions::RECTILINEAR: Ip = _("Rectilinear"); break;
1563  case PanoramaOptions::CYLINDRICAL: Ip = _("Cylindrical"); break;
1564  case PanoramaOptions::EQUIRECTANGULAR: Ip = _("Equirectangular"); break;
1565  }
1566  opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
1568  new PanoCommand::SetPanoOptionsCmd( pano, opt )
1569  );
1570  DEBUG_DEBUG ("Projection changed: " << lt << ":" << Ip )
1571 
1572 
1573 }
1574 #endif
1575 
1577 {
1578  if (m_pano.getActiveImages().empty()) return;
1579 
1580  // reset zoom so that full pano is visible
1581  ResetPreviewZoom();
1584  );
1585 }
1586 
1587 void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
1588 {
1589  if (m_pano.getNrOfImages() == 0) return;
1590 
1593  );
1594 }
1595 
1596 void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
1597 {
1598  if (m_pano.getActiveImages().empty()) return;
1599 
1600  DEBUG_TRACE("");
1603  fitPano.run();
1604  opt.setHFOV(fitPano.getResultHorizontalFOV());
1606 
1607  // reset zoom so that full pano is visible
1608  ResetPreviewZoom();
1609 
1612  );
1613 
1614  DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
1615 }
1616 
1617 void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
1618 {
1619  if (m_pano.getNrOfImages() == 0) return;
1620 
1621  HuginBase::UIntSet displayedImgs;
1623  {
1624  fill_set(displayedImgs, 0, m_pano.getNrOfImages() - 1);
1625  }
1626  else
1627  {
1629  {
1630  displayedImgs = m_pano.getActiveImages();
1631  };
1632  std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
1633  for (size_t i = 0; i < stackedImg.size(); ++i)
1634  {
1635  switch (m_selectAllMode)
1636  {
1638  displayedImgs.insert(*(stackedImg[i].rbegin()));
1639  break;
1640  case SELECT_DARKEST_IMAGES:
1641  displayedImgs.insert(*(stackedImg[i].begin()));
1642  break;
1643  case SELECT_MEDIAN_IMAGES:
1644  default:
1645  displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
1646  break;
1647  };
1648  };
1649  };
1651  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1652  );
1653 }
1654 
1655 void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
1656 {
1657  if (m_pano.getNrOfImages() == 0) return;
1658 
1660  for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
1661  m_ToggleButtons[i]->SetValue(false);
1662  }
1663  HuginBase::UIntSet displayedImgs;
1665  new PanoCommand::SetActiveImagesCmd(m_pano, displayedImgs)
1666  );
1667 }
1668 
1669 void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
1670 {
1671  if (m_pano.getNrOfImages() == 0) return;
1672 
1673  wxString text;
1674  double y;
1675  double p;
1676  double r;
1677  double x;
1678  double z;
1679 
1680  int index = m_DragModeChoice->GetSelection();
1681  switch (index) {
1682  case 0: //normal
1683  case 1: //normal, individual
1684  //@TODO limit numeric transform to selected images
1685  text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
1686  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1687  {
1688  wxBell();
1689  wxMessageBox(_("Yaw value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1690  return;
1691  }
1692  text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
1693  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
1694  {
1695  wxBell();
1696  wxMessageBox(_("Pitch value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1697  return;
1698  }
1699  text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
1700  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
1701  {
1702  wxBell();
1703  wxMessageBox(_("Roll value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1704  return;
1705  }
1707  new PanoCommand::RotatePanoCmd(m_pano, y, p, r)
1708  );
1709  break;
1710  case 2: //mosaic
1711  case 3: //mosaic, individual
1712  //@TODO limit numeric transform to selected images
1713  text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
1714  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
1715  {
1716  wxBell();
1717  wxMessageBox(_("X value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1718  return;
1719  }
1720  text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
1721  if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1722  {
1723  wxBell();
1724  wxMessageBox(_("Y value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1725  return;
1726  }
1727  text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
1728  if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
1729  {
1730  wxBell();
1731  wxMessageBox(_("Z value must be numeric."),_("Warning"),wxOK | wxICON_ERROR,this);
1732  return;
1733  }
1736  );
1737  break;
1738  }
1739 }
1740 
1741 void GLPreviewFrame::OnExposureChanged(wxCommandEvent & e)
1742 {
1744  // exposure
1745  wxString text = m_exposureTextCtrl->GetValue();
1746  DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
1747  double p = 0;
1748  if (text != wxT("")) {
1749  if (!hugin_utils::str2double(text, p)) {
1750  wxLogError(_("Value must be numeric."));
1751  return;
1752  }
1753  }
1754  opts.outputExposureValue = p;
1757  );
1758 }
1759 
1761 {
1766  );
1767 }
1768 
1770 {
1775  );
1776 }
1777 
1779 {
1781  // range compression
1782  const wxString text = m_rangeCompressionTextCtrl->GetValue();
1783  if (!text.IsEmpty())
1784  {
1785  double p = 0;
1786  if (!hugin_utils::str2double(text, p))
1787  {
1788  wxLogError(_("Value must be numeric."));
1789  return;
1790  };
1791  if (p < 0 || p>20)
1792  {
1793  wxLogError(_("Value for range compression is outside of valid range."));
1794  return;
1795  };
1796  if (p != opts.outputRangeCompression)
1797  {
1798  opts.outputRangeCompression = p;
1801  );
1802  };
1803  };
1804 }
1805 
1806 
1808 {
1810  int nParam = opts.m_projFeatures.numberOfParameters;
1811  std::vector<double> para = opts.getProjectionParameters();
1812  for (int i = 0; i < nParam; i++) {
1813  if (e.GetEventObject() == m_projParamTextCtrl[i]) {
1814  wxString text = m_projParamTextCtrl[i]->GetValue();
1815  DEBUG_INFO ("param " << i << ": = " << text.mb_str(wxConvLocal) );
1816  double p = 0;
1817  if (text != wxT("")) {
1818  if (!hugin_utils::str2double(text, p)) {
1819  wxLogError(_("Value must be numeric."));
1820  return;
1821  }
1822  }
1823  para[i] = p;
1824  }
1825  }
1826  opts.setProjectionParameters(para);
1829  );
1830 }
1831 
1833 {
1838  );
1839 };
1840 
1842 {
1844  const int nParam = opt.m_projFeatures.numberOfParameters;
1845  std::vector<double> para = opt.getProjectionParameters();
1846  for (int i = 0; i < nParam; i++)
1847  {
1848  if (e.GetEventObject() == m_projParamSlider[i])
1849  {
1850  // update
1851  para[i] = e.GetInt();
1852  break;
1853  }
1854  }
1855  opt.setProjectionParameters(para);
1856  opt.setHFOV(m_HFOVSlider->GetValue());
1857  opt.setVFOV(m_VFOVSlider->GetValue());
1859 }
1860 
1862 {
1864  const int nParam = opt.m_projFeatures.numberOfParameters;
1865  std::vector<double> para = opt.getProjectionParameters();
1866  for (int i = 0; i < nParam; i++)
1867  {
1868  if (e.GetEventObject() == m_projParamSlider[i])
1869  {
1870  // update
1871  para[i] = e.GetInt();
1872  m_projParamTextCtrl[i]->ChangeValue(wxString::Format("%d", e.GetInt()));
1873  break;
1874  }
1875  }
1876  opt.setProjectionParameters(para);
1877  // we only actually update the panorama fully when the mouse is released.
1878  // As we are dragging it we don't want to create undo events, but we would
1879  // like to update the display, so we change the GLViewer's ViewState and
1880  // request a redraw.
1882  m_GLPreview->Refresh();
1883 }
1884 
1885 void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
1886 {
1887  if (e.GetEventObject() == m_BlendModeChoice)
1888  {
1889  updateBlendMode();
1890  }
1891  else
1892  {
1893  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
1894  }
1895 }
1896 
1897 void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
1898 {
1899  if (drag_tool)
1900  {
1902  int index = m_DragModeChoice->GetSelection();
1903  switch (index) {
1904  case 0: //normal
1905  case 1:
1906  newDragMode=DragTool::drag_mode_normal;
1907  break;
1908  case 2: //mosaic
1909  case 3:
1910  newDragMode=DragTool::drag_mode_mosaic;
1911  break;
1912  }
1913  if(newDragMode==DragTool::drag_mode_mosaic)
1914  {
1916  {
1917  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?"),
1918 #ifdef __WXMSW__
1919  _("Hugin"),
1920 #else
1921  wxEmptyString,
1922 #endif
1923  wxYES_NO | wxICON_QUESTION, this) == wxYES)
1924  {
1926  }
1927  else
1928  {
1929  m_DragModeChoice->SetSelection(index-2);
1930  return;
1931  };
1932  };
1933  //switch overview mode to plane
1934  UpdateOverviewMode(1);
1935  m_OverviewModeChoice->SetSelection(1);
1936  }
1937  else
1938  {
1939  //new mode is normal
1940  //set overview back to panosphere mode
1941  UpdateOverviewMode(0);
1942  m_OverviewModeChoice->SetSelection(0);
1945  };
1946  //update drag mode
1947  drag_tool->setDragMode(newDragMode);
1949  // adjust the layout
1950  DragChoiceLayout(index);
1951  };
1952 };
1953 
1955 {
1956  size_t nr = m_pano.getNrOfImages();
1957  for (size_t i = 0 ; i < nr; i++)
1958  {
1959  if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
1960  m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
1961  {
1962  return true;
1963  };
1964  }
1965  return false;
1966 };
1967 
1969 {
1970  HuginBase::UIntSet imgs;
1972  size_t nr = newPan.getNrOfImages();
1973  for (size_t i = 0 ; i < nr ; i++)
1974  {
1975  HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
1976  img.setTranslationPlaneYaw(0);
1977  img.setTranslationPlanePitch(0);
1978  newPan.setSrcImage(i,img);
1979  imgs.insert(i);
1980  }
1983  );
1984 };
1985 
1987 {
1989  if (newMode == 1)
1990  {
1991  newOverviewMode = GLOverview::PANOSPHERE_INSIDE;
1992  }
1993  else
1994  {
1995  if (newMode == 2)
1996  {
1997  newOverviewMode = GLOverview::PLANE;
1998  };
1999  };
2000  if(m_GLOverview->GetMode()==newOverviewMode)
2001  {
2002  return true;
2003  };
2004  if (newOverviewMode == GLOverview::PLANE)
2005  {
2007  {
2009  return true;
2010  }
2011  else
2012  {
2013  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?"),
2014 #ifdef __WXMSW__
2015  _("Hugin"),
2016 #else
2017  wxEmptyString,
2018 #endif
2019  wxYES_NO | wxICON_QUESTION, this) == wxYES)
2020  {
2023  return true;
2024  }
2025  else
2026  {
2027  return false;
2028  };
2029  };
2030  }
2031  else
2032  {
2033  m_GLOverview->SetMode(newOverviewMode);
2034  return true;
2035  }
2036 };
2037 
2038 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
2039 {
2040  if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
2041  {
2044  //set drag mode to normal if new mode is panosphere mode
2046  {
2047  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
2048  OnDragChoice(e);
2049  };
2050  }
2051  else
2052  {
2053  //change mode was not successful or canceled by user, set mode choice back
2054  switch (m_GLOverview->GetMode())
2055  {
2057  m_OverviewModeChoice->SetSelection(0);
2058  break;
2060  m_OverviewModeChoice->SetSelection(1);
2061  break;
2062  case GLOverview::PLANE:
2063  m_OverviewModeChoice->SetSelection(2);
2064  break;
2065  };
2066  };
2067 };
2068 
2070 {
2071  // visibility of controls based on selected drag mode
2072  bool normalMode=index==0 || index==1;
2073  XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
2074  XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
2075  XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
2076  XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
2077  XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
2078  XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
2079  XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
2080  XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
2081  XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
2082  XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
2083  XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
2084  XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
2085  // redraw layout to compress empty space
2086  XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
2087 }
2088 
2089 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
2090 {
2091  if (m_pano.getActiveImages().size() > 0) {
2096  );
2097  }
2098 }
2099 
2100 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
2101 {
2103  opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
2106  );
2107 }
2108 
2109 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
2110 {
2112  opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
2115  );
2116 }
2117 
2118 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
2119 {
2120  if (e.GetEventObject() == m_ProjectionChoice) {
2122  int lt = m_ProjectionChoice->GetSelection();
2123  wxString Ip;
2127  );
2128  DEBUG_DEBUG ("Projection changed: " << lt);
2129  m_projection_panel->Layout();
2130  Refresh();
2131  } else {
2132  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2133  }
2134 }
2135 
2136 /* We don't have an OpenGL hdr display yet
2137 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
2138 {
2139  if (e.GetEventObject() == m_outputModeChoice) {
2140  PanoramaOptions opt = m_pano.getOptions();
2141  int lt = m_outputModeChoice->GetSelection();
2142  wxString Ip;
2143  opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
2144  PanoCommand::GlobalCmdHist::getInstance().addCommand(
2145  new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
2146  );
2147 
2148  } else {
2149  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2150  }
2151 }
2152 */
2153 
2154 void GLPreviewFrame::SetStatusMessage(wxString message)
2155 {
2156  SetStatusText(message, 0);
2157 }
2158 
2159 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
2160 {
2161  m_GLPreview->SetPhotometricCorrect(e.IsChecked());
2162 }
2163 
2165 {
2166  // create the tool objects.
2167  // we delay this until we have an OpenGL context so that they are free to
2168  // create texture objects and display lists before they are used.
2169  preview_helper = preview_helper_in;
2174  // bind corresponding menu events
2175  Bind(wxEVT_MENU, &GLPreviewFrame::OnCreateCP, this, ID_CREATE_CP);
2176  Bind(wxEVT_MENU, &GLPreviewFrame::OnRemoveCP, this, ID_REMOVE_CP);
2185 
2187  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2188  {
2190  };
2193 
2194  // activate tools that are always active.
2196  // update the blend mode which activates some tools
2197  updateBlendMode();
2199  // update toolbar
2201 }
2202 
2204 {
2205  panosphere_overview_helper = panosphere_overview_helper_in;
2211 
2214 
2216  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2217  {
2219  }
2220 
2221 
2225 
2228 
2229 
2230 
2231 }
2232 
2234 {
2235  plane_overview_helper = plane_overview_helper_in;
2238 
2242 
2245 
2248 
2249 }
2250 
2251 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
2252 {
2253  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2254  if (e.IsChecked())
2255  {
2256  m_BlendModeChoice->SetSelection(0);
2263 // TurnOffTools(preview_helper->ActivateTool(identify_tool));
2264 // TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
2265 // TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
2266  } else {
2267  identify_tool->setConstantOn(false);
2270 // preview_helper->DeactivateTool(identify_tool);
2271 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2272 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2274  }
2275  m_GLPreview->Refresh();
2276  m_GLOverview->Refresh();
2277 }
2278 
2279 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
2280 {
2281  if (!m_editCP_togglebutton->GetValue())
2282  {
2283  //process event only if edit cp tool is disabled
2284  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2285  if (e.IsChecked())
2286  {
2290  }
2291  else {
2295  }
2296  m_GLPreview->Refresh();
2297  m_GLOverview->Refresh();
2298  };
2299 }
2300 
2301 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
2302 {
2303  std::set<Tool*>::iterator i;
2304  for (i = tools.begin(); i != tools.end(); ++i)
2305  {
2306  if (*i == crop_tool)
2307  {
2308  // cover up the guidelines
2309  m_GLPreview->Refresh();
2310  } else if (*i == drag_tool)
2311  {
2312  // cover up its boxes
2313  m_GLPreview->Refresh();
2314  } else if (*i == identify_tool)
2315  {
2316  // disabled the identify tool, toggle its button off.
2317  m_identify_togglebutton->SetValue(false);
2318  // cover up its indicators and restore normal button colours.
2319  m_GLPreview->Refresh();
2320  m_GLOverview->Refresh();
2322  } else if (*i == preview_control_point_tool)
2323  {
2324  // disabled the control point tool.
2325  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2326  // cover up the control point lines.
2327  m_GLPreview->Refresh();
2328  m_GLOverview->Refresh();
2329  }
2330  }
2331 }
2332 
2333 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
2334  unsigned char red,
2335  unsigned char green,
2336  unsigned char blue)
2337 {
2338  // 0, 0, 0 indicates we want to go back to the system colour.
2339  // TODO: Maybe we should test this better on different themes.
2340 #if defined __WXMSW__ || defined __WXMAC__
2341  if (red || green || blue)
2342  {
2343  // the identify tool wants us to highlight an image button in the given
2344  // colour, to match up with the display in the preview.
2345  // on windows change the color of the surhugin_utils::rounding wxPanel
2346  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2347  }
2348  else
2349  {
2350  // return to the normal colour
2351  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(m_ToggleButtonPanel[image_nr]->GetParent()->GetBackgroundColour());
2352  }
2353  m_ToggleButtonPanel[image_nr]->Refresh();
2354 #else
2355  if (red || green || blue)
2356  {
2357  // change the color of the wxToggleButton
2358  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
2359  m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2360  // black should be visible on the button's vibrant colours.
2361  m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
2362  }
2363  else
2364  {
2365  // return to the normal colour
2366  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2367  m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
2368  m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
2369  };
2370  m_ToggleButtons[image_nr]->Refresh();
2371 #endif
2372 }
2373 
2375 {
2376  // when we turn off the identification tool, any buttons that were coloured
2377  // to match the image in the preview should be given back the system themed
2378  // colours.
2379  unsigned int nr_images = m_pano.getNrOfImages();
2380  for (unsigned image = 0; image < nr_images; image++)
2381  {
2382 #if defined __WXMSW__ || defined __WXMAC__
2383  m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
2384  m_ToggleButtonPanel[image]->Refresh();
2385 #else
2386  m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2387  m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
2388  m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
2389  m_ToggleButtons[image]->Refresh();
2390 #endif
2391  }
2392 }
2393 
2394 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
2395 {
2396  // blank status text as it refers to an old tool.
2397  SetStatusText(wxT(""), 0);
2398  if (e.IsChecked())
2399  {
2400  // deactivate delete cp tool if active
2402  m_editCP_togglebutton->SetValue(false);
2404  }
2405  else
2406  {
2408  };
2409  m_GLPreview->Refresh();
2410 };
2411 
2412 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
2413 {
2415  new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
2416  );
2417  //now toggle button and deactivate tool
2418  m_colorpicker_togglebutton->SetValue(false);
2419  //direct deactivation of tool does not work because this function is called by the tool itself
2420  //so we are send an event to deactivate the tool
2421  wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
2422  e.SetInt(0);
2423  GetEventHandler()->AddPendingEvent(e);
2424 };
2425 
2426 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
2427 {
2428  // blank status text as it refers to an old tool.
2429  SetStatusText(wxT(""), 0);
2430  if (e.IsChecked())
2431  {
2432  // deactivate color picker tool
2434  m_colorpicker_togglebutton->SetValue(false);
2435  // show automatically all cp
2438  }
2439  else
2440  {
2441  if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2442  {
2444  };
2446  };
2447  m_GLPreview->Refresh();
2448 };
2449 
2451  unsigned int image_number_in,
2452  wxToggleButton* identify_button_in,
2453  HuginBase::Panorama * m_pano_in)
2454 {
2455  image_number = image_number_in;
2456  m_identify_button = identify_button_in;
2457  m_pano = m_pano_in;
2458  // bind event handler
2459  Bind(wxEVT_ENTER_WINDOW, &ImageToogleButtonEventHandler::OnEnter, this);
2460  Bind(wxEVT_LEAVE_WINDOW, &ImageToogleButtonEventHandler::OnLeave, this);
2461  Bind(wxEVT_TOGGLEBUTTON, &ImageToogleButtonEventHandler::OnChange, this);
2462 }
2463 
2465 {
2466  // When using the identify tool, we want to identify image locations when
2467  // the user moves the mouse over the image buttons, but only if the image
2468  // is being shown.
2469  if (
2470  m_identify_button->GetValue() &&
2472  {
2473  std::vector<PreviewIdentifyTool**>::iterator it;
2474  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2475  (*(*it))->ShowImageNumber(image_number);
2476  }
2477  }
2478  e.Skip();
2479 }
2480 
2482 {
2483  // if the mouse left one of the image toggle buttons with the identification
2484  // tool active, we should stop showing the image indicator for that button.
2485  if (
2486  m_identify_button->GetValue() &&
2488  {
2489  std::vector<PreviewIdentifyTool**>::iterator it;
2490  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2491  (*(*it))->StopShowingImages();
2492  }
2493  }
2494  e.Skip();
2495 }
2496 
2498 {
2499  // the user is turning on or off an image using its button. We want to turn
2500  // the indicators on and off if appropriate correctly to. We use OnEnter
2501  // and OnLeave for the indicators, but these only work when the image is
2502  // showing, so we are carefull of the order:
2503  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
2504  wxMouseEvent null_event;
2505  if (e.IsChecked()) {
2506  activeImages.insert(image_number);
2508  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2509  );
2510  OnEnter(null_event);
2511  } else {
2512  OnLeave(null_event);
2513  activeImages.erase(image_number);
2515  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2516  );
2517  }
2518 }
2519 
2521  identify_tools.push_back(identify_tool_in);
2522 }
2523 
2525  : image_number(image_number), frame(frame_in), m_pano(m_pano)
2526 {
2527  Bind(wxEVT_ENTER_WINDOW, &ImageGroupButtonEventHandler::OnEnter, this);
2528  Bind(wxEVT_LEAVE_WINDOW, &ImageGroupButtonEventHandler::OnLeave, this);
2529  Bind(wxEVT_CHECKBOX, &ImageGroupButtonEventHandler::OnChange, this);
2530 }
2531 
2533  identify_tools.push_back(identify_tool_in);
2534 }
2535 
2536 
2538 {
2539  //mark the image
2540  if (m_pano->getActiveImages().count(image_number))
2541  {
2542  std::vector<PreviewIdentifyTool**>::iterator it;
2543  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2544  (*(*it))->ShowImageNumber(image_number);
2545  }
2546  }
2547  e.Skip();
2548 }
2549 
2551 {
2552  //unmark the image
2553  if (m_pano->getActiveImages().count(image_number))
2554  {
2555  std::vector<PreviewIdentifyTool**>::iterator it;
2556  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2557  (*(*it))->StopShowingImages();
2558  }
2559  }
2560  e.Skip();
2561 }
2562 
2564 {
2565  wxMouseEvent null_event;
2566  if (e.IsChecked()) {
2568  OnEnter(null_event);
2569  } else {
2570  OnLeave(null_event);
2572  }
2573 }
2574 
2576  drag_tools.push_back(drag_tool_in);
2577 }
2578 
2580 {
2581  return m_DragModeChoice->GetSelection()==1 ||
2582  m_DragModeChoice->GetSelection()==3;
2583 }
2584 
2585 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
2586  if (imageDragGroup.count(image_nr) == 0) {
2587  this->AddImageToDragGroup(image_nr, update_check_box);
2588  } else {
2589  this->RemoveImageFromDragGroup(image_nr, update_check_box);
2590  }
2591 }
2592 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
2593  imageDragGroup.erase(image_nr);
2594  if (update_check_box) {
2595  m_GroupToggleButtons[image_nr]->SetValue(false);
2596  }
2597 }
2598 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
2599  imageDragGroup.insert(image_nr);
2600  if (update_check_box) {
2601  m_GroupToggleButtons[image_nr]->SetValue(true);
2602  }
2603 }
2604 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
2605  imageDragGroup.swap(imageDragGroup_in);
2606  std::vector<wxCheckBox*>::iterator it;
2607  unsigned int nr = 0;
2608  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2609  (*it)->SetValue(imageDragGroup.count(nr++)>0);
2610  }
2611 }
2613  return imageDragGroup;
2614 }
2615 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
2616  imageDragGroup.clear();
2617  std::vector<wxCheckBox*>::iterator it;
2618  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2619  (*it)->SetValue(false);
2620  }
2621 }
2622 
2624 {
2625  std::vector<wxCheckBox*>::iterator it;
2626  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
2627  {
2628  (*it)->Show(isShown);
2629  }
2630  Layout();
2631 };
2632 
2635 {
2637  m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
2638  // update size
2639  m_BlendModeChoice->InvalidateBestSize();
2640  m_BlendModeChoice->GetParent()->Layout();
2641  Refresh();
2642  // get blend mode last state
2643  unsigned int oldMode = wxConfigBase::Get()->Read(wxT("/GLPreviewFrame/blendMode"), 0l);
2644  // limit old state to max available states
2645  if (oldMode >= m_BlendModeChoice->GetCount())
2646  {
2647  oldMode = 0;
2648  }
2649  m_BlendModeChoice->SetSelection(oldMode);
2650  updateBlendMode();
2651 };
2652 
2653 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
2654 {
2655  DEBUG_INFO("Dirty ROI Calc\n");
2656  if (m_pano.getActiveImages().empty())
2657  {
2658  return;
2659  };
2660 
2661  vigra::Rect2D newROI;
2662  {
2663  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2664  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2665  cropPano.run();
2666  if (cropPano.hasRunSuccessfully())
2667  {
2668  newROI = cropPano.getResultOptimalROI();
2669  };
2670  };
2671 
2672  //set the ROI - fail if the right/bottom is zero, meaning all zero
2673  if(!newROI.isEmpty())
2674  {
2676  opt.setROI(newROI);
2679  );
2680  }
2681 }
2682 
2683 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
2684 {
2685  DEBUG_INFO("Dirty ROI Calc\n");
2686  if (m_pano.getActiveImages().empty())
2687  {
2688  return;
2689  };
2690 
2691  vigra::Rect2D newROI;
2692  {
2693  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2694  HuginBase::UIntSet activeImages = m_pano.getActiveImages();
2695  std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
2696  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2697  //only use hdr autocrop for projects with stacks
2698  //otherwise fall back to "normal" autocrop
2699  if (stackImgs.size()<activeImages.size())
2700  {
2701  cropPano.setStacks(stackImgs);
2702  }
2703  cropPano.run();
2704  if (cropPano.hasRunSuccessfully())
2705  {
2706  newROI = cropPano.getResultOptimalROI();
2707  };
2708  };
2709 
2710  //set the ROI - fail if the right/bottom is zero, meaning all zero
2711  if(!newROI.isEmpty())
2712  {
2714  opt.setROI(newROI);
2717  );
2718  }
2719 }
2720 
2721 void GLPreviewFrame::OnAutocropOutside(wxCommandEvent& e)
2722 {
2723  DEBUG_INFO("Dirty ROI Calc\n");
2724  if (m_pano.getActiveImages().empty())
2725  {
2726  return;
2727  };
2728 
2729  vigra::Rect2D newROI;
2730  {
2731  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2732  HuginBase::CalculateOptimalROIOutside cropPano(m_pano, &progress);
2733  cropPano.run();
2734  if (cropPano.hasRunSuccessfully())
2735  {
2736  newROI = cropPano.getResultOptimalROI();
2737  };
2738  };
2739 
2740  //set the ROI - fail if the right/bottom is zero, meaning all zero
2741  if (!newROI.isEmpty())
2742  {
2744  opt.setROI(newROI);
2747  );
2748  }
2749 }
2750 
2751 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
2752 {
2753  ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
2754 };
2755 
2756 void GLPreviewFrame::SetMode(int newMode)
2757 {
2758  if(m_mode==newMode)
2759  return;
2760  SetStatusText(wxT(""), 0); // blank status text as it refers to an old tool.
2761  switch(m_mode)
2762  {
2763  case mode_assistant:
2764  case mode_preview:
2765  // switch off identify and show cp tool
2766  identify_tool->setConstantOn(false);
2770  m_colorpicker_togglebutton->SetValue(false);
2771 // preview_helper->DeactivateTool(identify_tool);
2772 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2773 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2775  m_editCP_togglebutton->SetValue(false);
2776 
2778  m_identify_togglebutton->SetValue(false);
2782  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2783  break;
2784  case mode_layout:
2785  // disable layout mode.
2789  // reactivate identify and camera tool when leaving layout mode
2794  m_GLPreview->SetLayoutMode(false);
2795  m_GLOverview->SetLayoutMode(false);
2796  // Switch the panorama mask back on.
2798  //restore blend mode
2800  updateBlendMode();
2801  break;
2802  case mode_projection:
2804  break;
2805  case mode_drag:
2809  if (individualDragging()) {
2810  std::vector<wxCheckBox*>::iterator it;
2811  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2812  (*it)->Show(false);
2813  }
2814  }
2815  break;
2816  case mode_crop:
2820  break;
2821  };
2822  m_mode=newMode;
2823  wxScrollEvent dummy;
2824  switch(m_mode)
2825  {
2826  case mode_assistant:
2827  case mode_preview:
2828  break;
2829  case mode_layout:
2830  //save blend mode setting, set to normal for layout mode
2831  non_layout_blend_mode=m_BlendModeChoice->GetSelection();
2832  m_BlendModeChoice->SetSelection(0);
2833  updateBlendMode();
2834  // turn off things not used in layout mode.
2837  // deactivate identify tool in layout mode
2841  m_GLPreview->SetLayoutMode(true);
2842  m_GLOverview->SetLayoutMode(true);
2846  // we need to update the meshes after switch to layout mode
2847  // otherwise the following update of scale has no meshes to scale
2848  m_GLPreview->Update();
2849  m_GLOverview->Update();
2850  OnLayoutScaleChange(dummy);
2851  break;
2852  case mode_projection:
2854  break;
2855  case mode_drag:
2859  if (individualDragging()) {
2860  std::vector<wxCheckBox*>::iterator it;
2861  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2862  (*it)->Show(true);
2863  }
2864  }
2865  break;
2866  case mode_crop:
2870  break;
2871  };
2872  //enable group checkboxes only for drag mode tab
2874  m_GLPreview->Refresh();
2875 };
2876 
2877 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
2878 {
2879  if(m_mode!=-1)
2880  SetMode(e.GetSelection());
2881 };
2882 
2883 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
2884 {
2885  if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
2886  {
2887  wxBell();
2888  e.Veto();
2889  };
2890 };
2891 
2892 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
2893 {
2895  long left, right, top, bottom;
2896  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
2897  wxLogError(_("Top needs to be an integer bigger than 0"));
2898  return;
2899  }
2900  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
2901  wxLogError(_("left needs to be an integer bigger than 0"));
2902  return;
2903  }
2904  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
2905  wxLogError(_("right needs to be an integer bigger than 0"));
2906  return;
2907  }
2908  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
2909  wxLogError(_("bottom needs to be an integer bigger than 0"));
2910  return;
2911  }
2912  opt.setROI(vigra::Rect2D(left, top, right, bottom));
2913  // make sure that left is really to the left of right
2914  if(opt.getROI().width()<1) {
2915  wxLogError(_("left boundary must be smaller than right"));
2917  return;
2918  }
2919  // make sure that top is really higher than bottom
2920  if(opt.getROI().height()<1) {
2921  wxLogError(_("top boundary must be smaller than bottom"));
2923  return;
2924  }
2925 
2928  );
2929 };
2930 
2931 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
2932 {
2934  opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
2936 };
2937 
2938 void GLPreviewFrame::OnSetCropAspect(wxCommandEvent& e)
2939 {
2940  // ask user for a setting
2941  SelectAspectRatioDialog dlg(this);
2942  if (dlg.ShowModal() == wxID_OK)
2943  {
2945  const double aspectRatio = dlg.GetSelectedAspectRatio();
2946  // calculate the new ROI, move crop if necessary
2947  int left = opt.getROI().left();
2948  int top = opt.getROI().top();
2949  int width = opt.getROI().width();
2950  int height = opt.getROI().height();
2951  const int newHeight = 1.0 * width / aspectRatio;
2952  if (newHeight > height)
2953  {
2954  const int newWidth = 1.0 * height * aspectRatio;
2955  left = left + (width - newWidth) / 2.0;
2956  width = newWidth;
2957  }
2958  else
2959  {
2960  top = top + (height - newHeight) / 2.0;
2961  height = newHeight;
2962  };
2963  // finally set new crop
2964  opt.setROI(vigra::Rect2D(left, top, left + width, top + height));
2966  };
2967 }
2968 
2969 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
2970 {
2972 
2973 
2974  wxString text = m_HFOVText->GetValue();
2975  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
2976  if (text == wxT("")) {
2977  return;
2978  }
2979 
2980  double hfov;
2981  if (!hugin_utils::str2double(text, hfov)) {
2982  wxLogError(_("Value must be numeric."));
2983  return;
2984  }
2985 
2986  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
2987  wxLogError(wxString::Format(
2988  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
2989  opt.getMaxHFOV()));
2990  hfov=opt.getMaxHFOV();
2991  }
2992  opt.setHFOV(hfov);
2993  // recalculate panorama height...
2996  );
2997 
2998  DEBUG_INFO ( "new hfov: " << hfov )
2999 };
3000 
3001 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
3002 {
3004 
3005  wxString text = m_VFOVText->GetValue();
3006  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
3007  if (text == wxT("")) {
3008  return;
3009  }
3010 
3011  double vfov;
3012  if (!hugin_utils::str2double(text, vfov)) {
3013  wxLogError(_("Value must be numeric."));
3014  return;
3015  }
3016 
3017  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
3018  wxLogError(wxString::Format(
3019  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
3020  opt.getMaxVFOV()));
3021  vfov = opt.getMaxVFOV();
3022  }
3023  opt.setVFOV(vfov);
3024  // recalculate panorama height...
3027  );
3028 
3029  DEBUG_INFO ( "new vfov: " << vfov )
3030 };
3031 
3033 {
3034  if(m_mode==mode_layout)
3035  {
3036  double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
3037  m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
3038  m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
3039  m_GLPreview->Refresh();
3040  m_GLOverview->Refresh();
3041  };
3042 };
3043 
3045 {
3047  double hfov = opts.getHFOV();
3048  double vfov = opts.getVFOV();
3049  double maxfov = hfov > vfov ? hfov : vfov;
3050  wxString message;
3051  // If this is set to true, offer rectilinear as an alternative if it fits.
3052  bool rectilinear_option = false;
3053  switch (opts.getProjection()) {
3055  if (maxfov > 120.0) {
3056  // wide rectilinear image
3057  message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
3058  if (vfov < 110) {
3059  message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
3060  } else {
3061  message += _("For a very wide panorama, try equirectangular projection instead.");
3062  }
3063  message += wxT(" ");
3064  message += _("You could also try Panini projection.");
3065  }
3066  break;
3068  if (vfov > 120.0) {
3069  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.");
3070  } else rectilinear_option = true;
3071  break;
3073  if (vfov < 110.0 && hfov > 120.0)
3074  {
3075  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.");
3076  } else rectilinear_option = true;
3077  break;
3079  if (maxfov < 280.0) {
3080  rectilinear_option = true;
3081  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.");
3082  }
3083  break;
3085  if (maxfov > 300.0) {
3086  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.");
3087  } else rectilinear_option = true;
3088  break;
3089  default:
3090  rectilinear_option = true;
3091  }
3092  if (rectilinear_option && maxfov < 110.0) {
3093  message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
3094  }
3095  if (message.IsEmpty()) {
3096  // no message needed.
3097  m_infoBar->Dismiss();
3098  } else {
3099  m_infoBar->ShowMessage(message, wxICON_INFORMATION);
3100  }
3101 };
3102 
3104 {
3105  m_showProjectionHints=new_value;
3107  {
3108  m_infoBar->Dismiss();
3109  };
3110 };
3111 
3113 {
3114  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."),
3115 #ifdef __WXMSW__
3116  _("Hugin"),
3117 #else
3118  wxT(""),
3119 #endif
3120  wxOK | wxICON_INFORMATION, this);
3121 
3122  wxConfigBase* cfg=wxConfigBase::Get();
3123  cfg->Write(wxT("/GLPreviewFrame/ShowProjectionHints"), false);
3124  m_showProjectionHints=false;
3125  cfg->Flush();
3126  e.Skip();
3127 };
3128 
3129 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
3130 {
3131  if(identify_tool)
3132  {
3133  identify_tool->UpdateWithNewImageSet(new_image_set);
3134  };
3136  {
3138  };
3140  {
3142  };
3143 }
3144 
3146  m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
3147  wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
3148  wxConfigBase* cfg=wxConfigBase::Get();
3149  cfg->Write(wxT("/GLPreviewFrame/PreviewBackground"), c);
3150  cfg->Flush();
3154  redrawPreview();
3155 }
3156 
3159 }
3160 
3161 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
3162 {
3163  if(preview_guide_tool)
3164  {
3165  int selection=e.GetSelection();
3167  //synchronize wxChoice in projection and crop tab
3168  m_GuideChoiceCrop->SetSelection(selection);
3169  m_GuideChoiceProj->SetSelection(selection);
3170  m_GuideChoiceDrag->SetSelection(selection);
3171  redrawPreview();
3172  };
3173 };
3174 
3176 {
3177  int old_selection=m_DragModeChoice->GetSelection();
3178  if(old_selection==wxNOT_FOUND)
3179  {
3180  old_selection=0;
3181  };
3182  m_DragModeChoice->Clear();
3183  m_DragModeChoice->Append(_("normal"));
3184  m_DragModeChoice->Append(_("normal, individual"));
3185  if(newLevel==GUI_EXPERT)
3186  {
3187  m_DragModeChoice->Append(_("mosaic"));
3188  m_DragModeChoice->Append(_("mosaic, individual"));
3189  m_DragModeChoice->SetSelection(old_selection);
3190  }
3191  else
3192  {
3193  if(old_selection>1)
3194  {
3195  m_DragModeChoice->SetSelection(old_selection-2);
3196  }
3197  else
3198  {
3199  m_DragModeChoice->SetSelection(old_selection);
3200  };
3201  };
3202  DragChoiceLayout(m_DragModeChoice->GetSelection());
3203  wxCommandEvent dummy;
3204  OnDragChoice(dummy);
3205 
3206  old_selection=m_OverviewModeChoice->GetSelection();
3207  m_OverviewModeChoice->Clear();
3208  m_OverviewModeChoice->Append(_("Panosphere (outside)"));
3209  m_OverviewModeChoice->Append(_("Panosphere (inside)"));
3210  if(newLevel==GUI_EXPERT)
3211  {
3212  m_OverviewModeChoice->Append(_("Mosaic plane"));
3213  };
3214  if(newLevel==GUI_EXPERT && old_selection==2)
3215  {
3216  m_OverviewModeChoice->SetSelection(2);
3217  }
3218  else
3219  {
3221  m_OverviewModeChoice->SetSelection(0);
3222  };
3223  if(newLevel==GUI_SIMPLE)
3224  {
3225 #ifdef __WXMAC__
3226  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
3227 #endif
3228  if(m_guiLevel!=GUI_SIMPLE)
3229  {
3230  GetMenuBar()->Remove(0);
3231  GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
3232  };
3233  SetTitle(MainFrame::Get()->GetTitle());
3234  }
3235  else
3236  {
3237 #ifdef __WXMAC__
3238  wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
3239 #endif
3240  if(m_guiLevel==GUI_SIMPLE)
3241  {
3242  GetMenuBar()->Remove(0);
3243  GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
3244  };
3245  SetTitle(_("Fast Panorama preview"));
3246  };
3247  m_guiLevel=newLevel;
3248  // update menu items
3249  switch(m_guiLevel)
3250  {
3251  case GUI_SIMPLE:
3252  GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
3253  break;
3254  case GUI_ADVANCED:
3255  GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
3256  break;
3257  case GUI_EXPERT:
3258  GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
3259  break;
3260  };
3261 };
3262 
3263 void GLPreviewFrame::AddUserDefinedSequence(int id, const wxString& desc, const wxString& help)
3264 {
3265  if (id == -1)
3266  {
3267  m_createButton->GetSplitButtonMenu()->AppendSeparator();
3268  }
3269  else
3270  {
3271  m_createButton->GetSplitButtonMenu()->Append(id, desc, help);
3272  };
3273 };
3274 
3275 void GLPreviewFrame::AddUserDefinedAssistant(int id, const wxString& desc, const wxString& help)
3276 {
3277  if (id == -1)
3278  {
3279  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
3280  }
3281  else
3282  {
3283  m_alignButton->GetSplitButtonMenu()->Append(id, desc, help);
3284  };
3285 };
3286 
3287 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
3288 {
3289  MainFrame::Get()->Show();
3290  MainFrame::Get()->Raise();
3291 };
3292 
3293 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
3294 {
3295  Close();
3296 };
3297 
3299 {
3300  if (wxConfig::Get()->Read(wxT("/ShowFisheyeCropHint"), 1l) == 1)
3301  {
3302  // show hint about crop and open tab when requested
3303  wxDialog dlg;
3304  wxXmlResource::Get()->LoadDialog(&dlg, NULL, wxT("fisheye_show_crop_dlg"));
3305  if (dlg.ShowModal() == wxID_OK)
3306  {
3307  MainFrame::Get()->ShowMaskEditor(0, true);
3308  };
3309  if (XRCCTRL(dlg, "fisheye_crop_dont_ask_checkbox", wxCheckBox)->IsChecked())
3310  {
3311  wxConfig::Get()->Write(wxT("/ShowFisheyeCropHint"), 0l);
3312  };
3313  };
3314 }
3315 
3316 void GLPreviewFrame::OnLoadImages(wxCommandEvent& e)
3317 {
3318  // load all images with default lens type
3319  LoadImages(-1);
3320 }
3321 
3322 void GLPreviewFrame::LoadImages(int preferredLensType)
3323 {
3324  // load the images.
3325  PanoOperation::AddImageOperation addImage(preferredLensType);
3326  HuginBase::UIntSet images;
3327  PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
3328  if(cmd==NULL)
3329  {
3330  return;
3331  }
3332  //distribute images only if the existing images are not connected
3333  //otherwise it would destruct the existing image pattern
3334  const bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
3335 
3336  const long autoAlign = wxConfigBase::Get()->Read(wxT("/Assistant/autoAlign"), HUGIN_ASS_AUTO_ALIGN);
3337  if (autoAlign)
3338  {
3340  wxCommandEvent dummy;
3341  OnAlign(dummy);
3342  }
3343  else
3344  {
3345  std::vector<PanoCommand::PanoCommand*> cmds;
3346  cmds.push_back(cmd);
3347  if(distributeImages)
3348  {
3349  cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
3350  cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
3351  };
3353  combinedCmd->setName("add and distribute images");
3355  if(m_pano.getImage(0).isCircularCrop())
3356  {
3357  // show hint about crop for fisheye images
3358  // skip display if we read the information from our lens database
3359  HuginBase::FileMetaData metaData=m_pano.getImage(0).getFileMetadata();
3360  HuginBase::FileMetaData::const_iterator pos = metaData.find("readProjectionFromDB");
3361  if(!(pos != metaData.end() && pos->second == "true"))
3362  {
3364  };
3365  };
3366  };
3367 }
3368 
3369 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
3370 {
3371  // run default assisant
3372  MainFrame::Get()->RunAssistant(this);
3373 }
3374 
3375 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
3376 {
3377  PanoOutputDialog dlg(this, m_pano, m_guiLevel);
3378  if(dlg.ShowModal()==wxID_OK)
3379  {
3382  );
3383  wxCommandEvent dummy;
3384  MainFrame::Get()->OnDoStitch(dummy);
3385  };
3386 }
3387 
3388 // remove cp, relatively easy, we get the selected cp from the edit cp tool
3389 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
3390 {
3393  // ask user, if pano should be optimized
3394  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3395  bool optimize = false;
3396  if (afterEditCPAction == 0)
3397  {
3398  wxDialog dlg;
3399  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3400  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())));
3401  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3402  dlg.Fit();
3403  optimize = (dlg.ShowModal() == wxID_OK);
3404  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3405  {
3406  if (optimize)
3407  {
3408  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3409  }
3410  else
3411  {
3412  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3413  };
3414  };
3415  }
3416  else
3417  {
3418  optimize = (afterEditCPAction == 1);
3419  }
3420  if (optimize)
3421  {
3422  // invoke optimization routine
3423  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3424  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3425  };
3426 };
3427 
3428 // some helper for cp generation
3429 // maximal width for remapping for cp generating
3430 #define MAX_DIMENSION 1600
3432 {
3433  size_t imgNr;
3434  vigra::BRGBImage image;
3435  vigra::BImage mask;
3436 };
3437 
3438 typedef std::vector<FindStruct> FindVector;
3439 typedef std::multimap<double, vigra::Diff2D> MapPoints;
3440 
3442 
3443 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
3444 {
3446  vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
3448  // some checking of conditions
3449  if (imgs.empty())
3450  {
3451  wxMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
3452 #ifdef __WXMSW__
3453  _("Hugin"),
3454 #else
3455  wxT(""),
3456 #endif
3457  wxOK | wxICON_INFORMATION, this);
3458  return;
3459  };
3460  if (imgs.size() < 2)
3461  {
3462  wxMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
3463 #ifdef __WXMSW__
3464  _("Hugin"),
3465 #else
3466  wxT(""),
3467 #endif
3468  wxOK | wxICON_INFORMATION, this);
3469  return;
3470  };
3471  if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
3472  {
3473  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?"),
3474 #ifdef __WXMSW__
3475  _("Hugin"),
3476 #else
3477  wxT(""),
3478 #endif
3479  wxYES_NO | wxICON_INFORMATION, this) == wxNO)
3480  {
3481  return;
3482  };
3483  }
3485  opts.setROI(roi);
3486  // don't correct exposure
3487  opts.outputExposureValue = 0;
3488  // don't use GPU for remapping, this interfere with the fast preview window
3489  opts.remapUsingGPU = false;
3490  // rescale if size is too big
3491  if (roi.width() > MAX_DIMENSION)
3492  {
3493  opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
3494  roi = opts.getROI();
3495  };
3496  HuginBase::CPVector cps;
3497  {
3498  ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
3499  // remap all images to panorama projection
3500  FindVector cpInfos;
3501  HuginBase::CPVector tempCps;
3502  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
3503  {
3504  const size_t imgNr = *it;
3505  if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
3506  {
3507  return;
3508  };
3509  FindStruct findStruct;
3510  findStruct.imgNr = imgNr;
3511  // remap image to panorama projection
3512  ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
3513 
3515  HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
3516  // don't correct exposure
3517  srcImg.setExposureValue(0);
3518  remapped->setPanoImage(srcImg, opts, roi);
3519  remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
3520  if (!progress.updateDisplay())
3521  {
3522  delete remapped;
3523  return;
3524  };
3525  findStruct.image = remapped->m_image;
3526  findStruct.mask = remapped->m_mask;
3527  delete remapped;
3528  cpInfos.push_back(findStruct);
3529  };
3530  if (cpInfos.size() > 1)
3531  {
3532  // match keypoints in all image pairs
3533  // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
3534  unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
3535  if (gridx < 1)
3536  {
3537  gridx = 1;
3538  }
3539  unsigned gridy = hugin_utils::roundi(25 / gridx);
3540  if (gridy < 1)
3541  {
3542  gridy = 1;
3543  }
3544  while (roi.width() / gridx < 20 && gridx > 1)
3545  {
3546  --gridx;
3547  };
3548  while (roi.height() / gridy < 20 && gridy > 1)
3549  {
3550  --gridy;
3551  };
3552  // template width
3553  const long templWidth = 20;
3554  // search width
3555  const long sWidth = 100;
3556  // match all images with all
3557  for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
3558  {
3559  if (!progress.updateDisplayValue(_("Matching interest points...")))
3560  {
3561  return;
3562  };
3563  vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
3564  // create a number of sub-regions
3565  std::vector<vigra::Rect2D> rects;
3566  for (unsigned party = 0; party < gridy; party++)
3567  {
3568  for (unsigned partx = 0; partx < gridx; partx++)
3569  {
3570  vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
3571  (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
3572  rect &= vigra::Rect2D(size);
3573  if (rect.width()>0 && rect.height()>0)
3574  {
3575  rects.push_back(rect);
3576  };
3577  };
3578  };
3579 
3580  if (!progress.updateDisplay())
3581  {
3582  return;
3583  };
3584 
3585 #pragma omp parallel for schedule(dynamic)
3586  for (int i = 0; i < rects.size(); ++i)
3587  {
3588  MapPoints points;
3589  vigra::Rect2D rect(rects[i]);
3590  // run interest point detection in sub-region
3591  vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
3592  //check if all points are inside the given image
3593  MapPoints validPoints;
3594  for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
3595  {
3596  if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
3597  {
3598  validPoints.insert(*it);
3599  };
3600  };
3601 
3602  if (!validPoints.empty())
3603  {
3604  // now fine-tune the interest points with all other images
3605  for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
3606  {
3607  unsigned nGood = 0;
3608  // loop over all points, starting with the highest corner score
3609  for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
3610  {
3611  if (nGood >= 2)
3612  {
3613  // we have enough points, stop
3614  break;
3615  }
3616  //check if point is covered by second image
3617  if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
3618  {
3619  continue;
3620  };
3621  // finally fine-tune point
3622  vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
3623  cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
3624  if (res.maxi < 0.9)
3625  {
3626  continue;
3627  }
3628  nGood++;
3629  // add control point
3630  {
3631  hugin_omp::ScopedLock sl(cpLock);
3632  tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
3633  cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
3634  };
3635  };
3636  };
3637  };
3638  };
3639  // free memory
3640  cpInfos[img1].image.resize(0, 0);
3641  cpInfos[img1].mask.resize(0, 0);
3642  };
3643 
3644  // transform coordinates back to image space
3645  for (size_t i = 0; i < tempCps.size(); ++i)
3646  {
3647  HuginBase::ControlPoint cp = tempCps[i];
3648  hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
3649  hugin_utils::FDiff2D p1Img;
3650  HuginBase::PTools::Transform transform;
3651  transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
3652  if (transform.transformImgCoord(p1Img, p1))
3653  {
3654  hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
3655  hugin_utils::FDiff2D p2Img;
3656  transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
3657  if (transform.transformImgCoord(p2Img, p2))
3658  {
3659  cp.x1 = p1Img.x;
3660  cp.y1 = p1Img.y;
3661  cp.x2 = p2Img.x;
3662  cp.y2 = p2Img.y;
3663  cps.push_back(cp);
3664  };
3665  };
3666  };
3667 
3668  if (!cps.empty())
3669  {
3670  // check newly found control points
3671  // create copy
3673  // remove all cps and set only the new found cp
3674  copyPano.setCtrlPoints(cps);
3675  // now create a subpano with only the selected images
3676  HuginBase::Panorama subPano = copyPano.getSubset(imgs);
3677  // clean control points
3678  if (!progress.updateDisplayValue(_("Checking results...")))
3679  {
3680  return;
3681  };
3683  HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
3685  if (!invalidCP.empty())
3686  {
3687  for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
3688  {
3689  cps.erase(cps.begin() + *it);
3690  };
3691  }
3692  // force closing progress dialog
3693  if (!progress.updateDisplayValue())
3694  {
3695  return;
3696  };
3698  // ask user, if pano should be optimized
3699  long afterEditCPAction = wxConfig::Get()->Read(wxT("/EditCPAfterAction"), 0l);
3700  bool optimize = false;
3701  if (afterEditCPAction == 0)
3702  {
3703  // close progress window, otherwise the dialog don't autoamtically get the focus
3704  wxYield();
3705  wxDialog dlg;
3706  wxXmlResource::Get()->LoadDialog(&dlg, this, wxT("edit_cp_optimize_dialog"));
3707  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())));
3708  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3709  dlg.Fit();
3710  optimize = (dlg.ShowModal() == wxID_OK);
3711  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3712  {
3713  if (optimize)
3714  {
3715  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 1l);
3716  }
3717  else
3718  {
3719  wxConfig::Get()->Write(wxT("/EditCPAfterAction"), 2l);
3720  };
3721  };
3722  }
3723  else
3724  {
3725  optimize = (afterEditCPAction == 1);
3726  }
3727  if (optimize)
3728  {
3729  // invoke optimization routine
3730  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3731  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3732  };
3733  };
3734  };
3735  };
3736  // finally redraw
3737  m_GLPreview->Update();
3738  m_GLPreview->Refresh();
3739 };
3740 
3741 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
3742 {
3743  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 0l);
3745 };
3746 
3747 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
3748 {
3749  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 1l);
3751 };
3752 
3754 {
3755  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 2l);
3757 };
3758 
3760 {
3761  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllMode"), 3l);
3763 };
3764 
3766 {
3767  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), true);
3768  m_selectKeepSelection = true;
3769 };
3770 
3772 {
3773  wxConfig::Get()->Write(wxT("/GLPreviewFrame/SelectAllKeepSelection"), false);
3774  m_selectKeepSelection = false;
3775 };
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:95
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:301
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:289
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:2415
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:356
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:102
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
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 SetBitmap(const wxBitmapBundle &bitmap)
sets bitmap bundle
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:645
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
GLwxAuiFloatingFrame(wxWindow *parent, GLwxAuiManager *owner_mgr, const wxAuiPaneInfo &pane, wxWindowID id=wxID_ANY, long style=wxRESIZE_BORDER|wxSYSTEM_MENU|wxCAPTION|wxFRAME_FLOAT_ON_PARENT|wxCLIP_CHILDREN)
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:492
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 OnLayoutScaleChange(wxCommandEvent &e)
event handler for change scale of layout mode
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:2153
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:210
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:151
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:156
static GlobalCmdHist & getInstance()
PanosphereOverviewToolHelper * panosphere_overview_helper
virtual void SetLayoutMode(bool state)
Definition: GLViewer.cpp:295
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:2024
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)
straighten panorama horizontically
Definition: PanoCommand.h:259
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
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:314
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:1675
void OnChangeProjectionParam(wxScrollEvent &e)
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:307
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
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:385
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)
void OnTrackChangeProjectionParam(wxScrollEvent &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:485
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
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:122
struct to hold a image state for stitching
wxString Components2Str(const HuginGraph::ImageGraph::Components &comp)
Definition: huginApp.cpp:83
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