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(wxEmptyString,1);
212  SetStatusText(wxEmptyString,2);
213  wxConfigBase * cfg = wxConfigBase::Get();
214 
215  wxPanel *tool_panel = wxXmlResource::Get()->LoadPanel(this,"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, "preview_simple_menu");
242  m_filemenuSimple=wxXmlResource::Get()->LoadMenu("preview_file_menu");
243  m_filemenuAdvanced = wxXmlResource::Get()->LoadMenu("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("/GLPreviewFrame/PreviewBackground",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("/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("preview_select_menu");
283  m_selectAllButton->Bind(wxEVT_BUTTON, &GLPreviewFrame::OnShowAll, this);
284  // read last used setting
285  long mode = cfg->Read("/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("/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("/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,"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("/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("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("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("/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, "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() + "data/hugin.ico",wxBITMAP_TYPE_ICO);
733  SetIcons(myIcons);
734 #else
735  wxIcon myIcon(huginApp::Get()->GetXRCPath() + "data/hugin.png",wxBITMAP_TYPE_PNG);
736  SetIcon(myIcon);
737 #endif
738 
739  m_pano.addObserver(this);
740 
741  hugin_utils::RestoreFramePosition(this, "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("/GLPreviewFrame/ShowProjectionHints", HUGIN_SHOW_PROJECTION_HINTS) == 1;
749  m_degDigits = wxConfigBase::Get()->Read("/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("/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("/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("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  hugin_utils::StoreFramePosition(this, "GLPreviewFrame");
849 
850  if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
851  cfg->Write("/GLPreviewFrame/isShown", 1l);
852  } else {
853  cfg->Write("/GLPreviewFrame/isShown", 0l);
854  }
855 
856  cfg->Write("/GLPreviewFrame/blendMode", m_BlendModeChoice->GetSelection());
857  cfg->Write("/GLPreviewFrame/OpenGLLayout", m_mgr->SavePerspective());
858  cfg->Write("/GLPreviewFrame/overview_hidden", !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
859  cfg->Write("/GLPreviewFrame/showPreviewGrid", GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
860  cfg->Write("/GLPreviewFrame/individualDragMode", individualDragging());
861  cfg->Write("/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("%d", opts.getROI().left() ));
1029  m_ROIRightTxt->ChangeValue(wxString::Format("%d", opts.getROI().right() ));
1030  m_ROITopTxt->ChangeValue(wxString::Format("%d", opts.getROI().top() ));
1031  m_ROIBottomTxt->ChangeValue(wxString::Format("%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("%.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(" %d ",*it),
1322  wxDefaultPosition, wxDefaultSize,
1323  wxBU_EXACTFIT);
1324 
1325  wxCheckBox *butcheck = new wxCheckBox(pan, wxID_ANY, wxEmptyString);
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("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("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  hugin_utils::HuginMessageBox(_("Yaw value must be numeric."), _("Hugin"), 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  hugin_utils::HuginMessageBox(_("Pitch value must be numeric."), _("Hugin"), 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  hugin_utils::HuginMessageBox(_("Roll value must be numeric."), _("Hugin"), 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  hugin_utils::HuginMessageBox(_("X value must be numeric."), _("Hugin"), 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  hugin_utils::HuginMessageBox(_("Y value must be numeric."), _("Hugin"), 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  hugin_utils::HuginMessageBox(_("Z value must be numeric."), _("Hugin"), 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 != wxEmptyString) {
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 != wxEmptyString) {
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 (hugin_utils::HuginMessageBox(_("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  _("Hugin"), wxYES_NO | wxICON_QUESTION, this) == wxYES)
1919  {
1921  }
1922  else
1923  {
1924  m_DragModeChoice->SetSelection(index-2);
1925  return;
1926  };
1927  };
1928  //switch overview mode to plane
1929  UpdateOverviewMode(1);
1930  m_OverviewModeChoice->SetSelection(1);
1931  }
1932  else
1933  {
1934  //new mode is normal
1935  //set overview back to panosphere mode
1936  UpdateOverviewMode(0);
1937  m_OverviewModeChoice->SetSelection(0);
1940  };
1941  //update drag mode
1942  drag_tool->setDragMode(newDragMode);
1944  // adjust the layout
1945  DragChoiceLayout(index);
1946  };
1947 };
1948 
1950 {
1951  size_t nr = m_pano.getNrOfImages();
1952  for (size_t i = 0 ; i < nr; i++)
1953  {
1954  if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
1955  m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
1956  {
1957  return true;
1958  };
1959  }
1960  return false;
1961 };
1962 
1964 {
1965  HuginBase::UIntSet imgs;
1967  size_t nr = newPan.getNrOfImages();
1968  for (size_t i = 0 ; i < nr ; i++)
1969  {
1970  HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
1971  img.setTranslationPlaneYaw(0);
1972  img.setTranslationPlanePitch(0);
1973  newPan.setSrcImage(i,img);
1974  imgs.insert(i);
1975  }
1978  );
1979 };
1980 
1982 {
1984  if (newMode == 1)
1985  {
1986  newOverviewMode = GLOverview::PANOSPHERE_INSIDE;
1987  }
1988  else
1989  {
1990  if (newMode == 2)
1991  {
1992  newOverviewMode = GLOverview::PLANE;
1993  };
1994  };
1995  if(m_GLOverview->GetMode()==newOverviewMode)
1996  {
1997  return true;
1998  };
1999  if (newOverviewMode == GLOverview::PLANE)
2000  {
2002  {
2004  return true;
2005  }
2006  else
2007  {
2008  if (hugin_utils::HuginMessageBox(_("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?"),
2009  _("Hugin"), wxYES_NO | wxICON_QUESTION, this) == wxYES)
2010  {
2013  return true;
2014  }
2015  else
2016  {
2017  return false;
2018  };
2019  };
2020  }
2021  else
2022  {
2023  m_GLOverview->SetMode(newOverviewMode);
2024  return true;
2025  }
2026 };
2027 
2028 void GLPreviewFrame::OnOverviewModeChoice( wxCommandEvent & e)
2029 {
2030  if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
2031  {
2034  //set drag mode to normal if new mode is panosphere mode
2036  {
2037  m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
2038  OnDragChoice(e);
2039  };
2040  }
2041  else
2042  {
2043  //change mode was not successful or canceled by user, set mode choice back
2044  switch (m_GLOverview->GetMode())
2045  {
2047  m_OverviewModeChoice->SetSelection(0);
2048  break;
2050  m_OverviewModeChoice->SetSelection(1);
2051  break;
2052  case GLOverview::PLANE:
2053  m_OverviewModeChoice->SetSelection(2);
2054  break;
2055  };
2056  };
2057 };
2058 
2060 {
2061  // visibility of controls based on selected drag mode
2062  bool normalMode=index==0 || index==1;
2063  XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
2064  XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
2065  XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
2066  XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
2067  XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
2068  XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
2069  XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
2070  XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
2071  XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
2072  XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
2073  XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
2074  XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
2075  // redraw layout to compress empty space
2076  XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
2077 }
2078 
2079 void GLPreviewFrame::OnDefaultExposure( wxCommandEvent & e )
2080 {
2081  if (m_pano.getActiveImages().size() > 0) {
2086  );
2087  }
2088 }
2089 
2090 void GLPreviewFrame::OnIncreaseExposure( wxSpinEvent & e )
2091 {
2093  opt.outputExposureValue = opt.outputExposureValue + 1.0/3;
2096  );
2097 }
2098 
2099 void GLPreviewFrame::OnDecreaseExposure( wxSpinEvent & e )
2100 {
2102  opt.outputExposureValue = opt.outputExposureValue - 1.0/3;
2105  );
2106 }
2107 
2108 void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
2109 {
2110  if (e.GetEventObject() == m_ProjectionChoice) {
2112  int lt = m_ProjectionChoice->GetSelection();
2113  wxString Ip;
2117  );
2118  DEBUG_DEBUG ("Projection changed: " << lt);
2119  m_projection_panel->Layout();
2120  Refresh();
2121  } else {
2122  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2123  }
2124 }
2125 
2126 /* We don't have an OpenGL hdr display yet
2127 void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
2128 {
2129  if (e.GetEventObject() == m_outputModeChoice) {
2130  PanoramaOptions opt = m_pano.getOptions();
2131  int lt = m_outputModeChoice->GetSelection();
2132  wxString Ip;
2133  opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
2134  PanoCommand::GlobalCmdHist::getInstance().addCommand(
2135  new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
2136  );
2137 
2138  } else {
2139  // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2140  }
2141 }
2142 */
2143 
2144 void GLPreviewFrame::SetStatusMessage(wxString message)
2145 {
2146  SetStatusText(message, 0);
2147 }
2148 
2149 void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
2150 {
2151  m_GLPreview->SetPhotometricCorrect(e.IsChecked());
2152 }
2153 
2155 {
2156  // create the tool objects.
2157  // we delay this until we have an OpenGL context so that they are free to
2158  // create texture objects and display lists before they are used.
2159  preview_helper = preview_helper_in;
2164  // bind corresponding menu events
2165  Bind(wxEVT_MENU, &GLPreviewFrame::OnCreateCP, this, ID_CREATE_CP);
2166  Bind(wxEVT_MENU, &GLPreviewFrame::OnRemoveCP, this, ID_REMOVE_CP);
2175 
2177  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2178  {
2180  };
2183 
2184  // activate tools that are always active.
2186  // update the blend mode which activates some tools
2187  updateBlendMode();
2189  // update toolbar
2191 }
2192 
2194 {
2195  panosphere_overview_helper = panosphere_overview_helper_in;
2201 
2204 
2206  if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2207  {
2209  }
2210 
2211 
2215 
2218 
2219 
2220 
2221 }
2222 
2224 {
2225  plane_overview_helper = plane_overview_helper_in;
2228 
2232 
2235 
2238 
2239 }
2240 
2241 void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
2242 {
2243  SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2244  if (e.IsChecked())
2245  {
2246  m_BlendModeChoice->SetSelection(0);
2253 // TurnOffTools(preview_helper->ActivateTool(identify_tool));
2254 // TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
2255 // TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
2256  } else {
2257  identify_tool->setConstantOn(false);
2260 // preview_helper->DeactivateTool(identify_tool);
2261 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2262 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2264  }
2265  m_GLPreview->Refresh();
2266  m_GLOverview->Refresh();
2267 }
2268 
2269 void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
2270 {
2271  if (!m_editCP_togglebutton->GetValue())
2272  {
2273  //process event only if edit cp tool is disabled
2274  SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2275  if (e.IsChecked())
2276  {
2280  }
2281  else {
2285  }
2286  m_GLPreview->Refresh();
2287  m_GLOverview->Refresh();
2288  };
2289 }
2290 
2291 void GLPreviewFrame::TurnOffTools(std::set<Tool*> tools)
2292 {
2293  std::set<Tool*>::iterator i;
2294  for (i = tools.begin(); i != tools.end(); ++i)
2295  {
2296  if (*i == crop_tool)
2297  {
2298  // cover up the guidelines
2299  m_GLPreview->Refresh();
2300  } else if (*i == drag_tool)
2301  {
2302  // cover up its boxes
2303  m_GLPreview->Refresh();
2304  } else if (*i == identify_tool)
2305  {
2306  // disabled the identify tool, toggle its button off.
2307  m_identify_togglebutton->SetValue(false);
2308  // cover up its indicators and restore normal button colours.
2309  m_GLPreview->Refresh();
2310  m_GLOverview->Refresh();
2312  } else if (*i == preview_control_point_tool)
2313  {
2314  // disabled the control point tool.
2315  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2316  // cover up the control point lines.
2317  m_GLPreview->Refresh();
2318  m_GLOverview->Refresh();
2319  }
2320  }
2321 }
2322 
2323 void GLPreviewFrame::SetImageButtonColour(unsigned int image_nr,
2324  unsigned char red,
2325  unsigned char green,
2326  unsigned char blue)
2327 {
2328  // 0, 0, 0 indicates we want to go back to the system colour.
2329  // TODO: Maybe we should test this better on different themes.
2330 #if defined __WXMSW__ || defined __WXMAC__
2331  if (red || green || blue)
2332  {
2333  // the identify tool wants us to highlight an image button in the given
2334  // colour, to match up with the display in the preview.
2335  // on windows change the color of the surhugin_utils::rounding wxPanel
2336  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2337  }
2338  else
2339  {
2340  // return to the normal colour
2341  m_ToggleButtonPanel[image_nr]->SetBackgroundColour(m_ToggleButtonPanel[image_nr]->GetParent()->GetBackgroundColour());
2342  }
2343  m_ToggleButtonPanel[image_nr]->Refresh();
2344 #else
2345  if (red || green || blue)
2346  {
2347  // change the color of the wxToggleButton
2348  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
2349  m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2350  // black should be visible on the button's vibrant colours.
2351  m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
2352  }
2353  else
2354  {
2355  // return to the normal colour
2356  m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2357  m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
2358  m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
2359  };
2360  m_ToggleButtons[image_nr]->Refresh();
2361 #endif
2362 }
2363 
2365 {
2366  // when we turn off the identification tool, any buttons that were coloured
2367  // to match the image in the preview should be given back the system themed
2368  // colours.
2369  unsigned int nr_images = m_pano.getNrOfImages();
2370  for (unsigned image = 0; image < nr_images; image++)
2371  {
2372 #if defined __WXMSW__ || defined __WXMAC__
2373  m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
2374  m_ToggleButtonPanel[image]->Refresh();
2375 #else
2376  m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2377  m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
2378  m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
2379  m_ToggleButtons[image]->Refresh();
2380 #endif
2381  }
2382 }
2383 
2384 void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
2385 {
2386  // blank status text as it refers to an old tool.
2387  SetStatusText(wxEmptyString, 0);
2388  if (e.IsChecked())
2389  {
2390  // deactivate delete cp tool if active
2392  m_editCP_togglebutton->SetValue(false);
2394  }
2395  else
2396  {
2398  };
2399  m_GLPreview->Refresh();
2400 };
2401 
2402 void GLPreviewFrame::UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
2403 {
2405  new PanoCommand::UpdateWhiteBalance(m_pano, redFactor, blueFactor)
2406  );
2407  //now toggle button and deactivate tool
2408  m_colorpicker_togglebutton->SetValue(false);
2409  //direct deactivation of tool does not work because this function is called by the tool itself
2410  //so we are send an event to deactivate the tool
2411  wxCommandEvent e(wxEVT_COMMAND_TOOL_CLICKED, XRCID("preview_color_picker_tool"));
2412  e.SetInt(0);
2413  GetEventHandler()->AddPendingEvent(e);
2414 };
2415 
2416 void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
2417 {
2418  // blank status text as it refers to an old tool.
2419  SetStatusText(wxEmptyString, 0);
2420  if (e.IsChecked())
2421  {
2422  // deactivate color picker tool
2424  m_colorpicker_togglebutton->SetValue(false);
2425  // show automatically all cp
2428  }
2429  else
2430  {
2431  if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2432  {
2434  };
2436  };
2437  m_GLPreview->Refresh();
2438 };
2439 
2441  unsigned int image_number_in,
2442  wxToggleButton* identify_button_in,
2443  HuginBase::Panorama * m_pano_in)
2444 {
2445  image_number = image_number_in;
2446  m_identify_button = identify_button_in;
2447  m_pano = m_pano_in;
2448  // bind event handler
2449  Bind(wxEVT_ENTER_WINDOW, &ImageToogleButtonEventHandler::OnEnter, this);
2450  Bind(wxEVT_LEAVE_WINDOW, &ImageToogleButtonEventHandler::OnLeave, this);
2451  Bind(wxEVT_TOGGLEBUTTON, &ImageToogleButtonEventHandler::OnChange, this);
2452 }
2453 
2455 {
2456  // When using the identify tool, we want to identify image locations when
2457  // the user moves the mouse over the image buttons, but only if the image
2458  // is being shown.
2459  if (
2460  m_identify_button->GetValue() &&
2462  {
2463  std::vector<PreviewIdentifyTool**>::iterator it;
2464  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2465  (*(*it))->ShowImageNumber(image_number);
2466  }
2467  }
2468  e.Skip();
2469 }
2470 
2472 {
2473  // if the mouse left one of the image toggle buttons with the identification
2474  // tool active, we should stop showing the image indicator for that button.
2475  if (
2476  m_identify_button->GetValue() &&
2478  {
2479  std::vector<PreviewIdentifyTool**>::iterator it;
2480  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2481  (*(*it))->StopShowingImages();
2482  }
2483  }
2484  e.Skip();
2485 }
2486 
2488 {
2489  // the user is turning on or off an image using its button. We want to turn
2490  // the indicators on and off if appropriate correctly to. We use OnEnter
2491  // and OnLeave for the indicators, but these only work when the image is
2492  // showing, so we are carefull of the order:
2493  HuginBase::UIntSet activeImages = m_pano->getActiveImages();
2494  wxMouseEvent null_event;
2495  if (e.IsChecked()) {
2496  activeImages.insert(image_number);
2498  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2499  );
2500  OnEnter(null_event);
2501  } else {
2502  OnLeave(null_event);
2503  activeImages.erase(image_number);
2505  new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2506  );
2507  }
2508 }
2509 
2511  identify_tools.push_back(identify_tool_in);
2512 }
2513 
2515  : image_number(image_number), frame(frame_in), m_pano(m_pano)
2516 {
2517  Bind(wxEVT_ENTER_WINDOW, &ImageGroupButtonEventHandler::OnEnter, this);
2518  Bind(wxEVT_LEAVE_WINDOW, &ImageGroupButtonEventHandler::OnLeave, this);
2519  Bind(wxEVT_CHECKBOX, &ImageGroupButtonEventHandler::OnChange, this);
2520 }
2521 
2523  identify_tools.push_back(identify_tool_in);
2524 }
2525 
2526 
2528 {
2529  //mark the image
2530  if (m_pano->getActiveImages().count(image_number))
2531  {
2532  std::vector<PreviewIdentifyTool**>::iterator it;
2533  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2534  (*(*it))->ShowImageNumber(image_number);
2535  }
2536  }
2537  e.Skip();
2538 }
2539 
2541 {
2542  //unmark the image
2543  if (m_pano->getActiveImages().count(image_number))
2544  {
2545  std::vector<PreviewIdentifyTool**>::iterator it;
2546  for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2547  (*(*it))->StopShowingImages();
2548  }
2549  }
2550  e.Skip();
2551 }
2552 
2554 {
2555  wxMouseEvent null_event;
2556  if (e.IsChecked()) {
2558  OnEnter(null_event);
2559  } else {
2560  OnLeave(null_event);
2562  }
2563 }
2564 
2566  drag_tools.push_back(drag_tool_in);
2567 }
2568 
2570 {
2571  return m_DragModeChoice->GetSelection()==1 ||
2572  m_DragModeChoice->GetSelection()==3;
2573 }
2574 
2575 void GLPreviewFrame::ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box) {
2576  if (imageDragGroup.count(image_nr) == 0) {
2577  this->AddImageToDragGroup(image_nr, update_check_box);
2578  } else {
2579  this->RemoveImageFromDragGroup(image_nr, update_check_box);
2580  }
2581 }
2582 void GLPreviewFrame::RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box) {
2583  imageDragGroup.erase(image_nr);
2584  if (update_check_box) {
2585  m_GroupToggleButtons[image_nr]->SetValue(false);
2586  }
2587 }
2588 void GLPreviewFrame::AddImageToDragGroup(unsigned int image_nr, bool update_check_box) {
2589  imageDragGroup.insert(image_nr);
2590  if (update_check_box) {
2591  m_GroupToggleButtons[image_nr]->SetValue(true);
2592  }
2593 }
2594 void GLPreviewFrame::SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box) {
2595  imageDragGroup.swap(imageDragGroup_in);
2596  std::vector<wxCheckBox*>::iterator it;
2597  unsigned int nr = 0;
2598  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2599  (*it)->SetValue(imageDragGroup.count(nr++)>0);
2600  }
2601 }
2603  return imageDragGroup;
2604 }
2605 void GLPreviewFrame::ClearDragGroupImages(bool update_check_box) {
2606  imageDragGroup.clear();
2607  std::vector<wxCheckBox*>::iterator it;
2608  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2609  (*it)->SetValue(false);
2610  }
2611 }
2612 
2614 {
2615  std::vector<wxCheckBox*>::iterator it;
2616  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
2617  {
2618  (*it)->Show(isShown);
2619  }
2620  Layout();
2621 };
2622 
2625 {
2627  m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
2628  // update size
2629  m_BlendModeChoice->InvalidateBestSize();
2630  m_BlendModeChoice->GetParent()->Layout();
2631  Refresh();
2632  // get blend mode last state
2633  unsigned int oldMode = wxConfigBase::Get()->Read("/GLPreviewFrame/blendMode", 0l);
2634  // limit old state to max available states
2635  if (oldMode >= m_BlendModeChoice->GetCount())
2636  {
2637  oldMode = 0;
2638  }
2639  m_BlendModeChoice->SetSelection(oldMode);
2640  updateBlendMode();
2641 };
2642 
2643 void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
2644 {
2645  DEBUG_INFO("Dirty ROI Calc\n");
2646  if (m_pano.getActiveImages().empty())
2647  {
2648  return;
2649  };
2650 
2651  vigra::Rect2D newROI;
2652  {
2653  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2654  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2655  cropPano.run();
2656  if (cropPano.hasRunSuccessfully())
2657  {
2658  newROI = cropPano.getResultOptimalROI();
2659  };
2660  };
2661 
2662  //set the ROI - fail if the right/bottom is zero, meaning all zero
2663  if(!newROI.isEmpty())
2664  {
2666  opt.setROI(newROI);
2669  );
2670  }
2671 }
2672 
2673 void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
2674 {
2675  DEBUG_INFO("Dirty ROI Calc\n");
2676  if (m_pano.getActiveImages().empty())
2677  {
2678  return;
2679  };
2680 
2681  vigra::Rect2D newROI;
2682  {
2683  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2684  HuginBase::UIntSet activeImages = m_pano.getActiveImages();
2685  std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
2686  HuginBase::CalculateOptimalROI cropPano(m_pano, &progress);
2687  //only use hdr autocrop for projects with stacks
2688  //otherwise fall back to "normal" autocrop
2689  if (stackImgs.size()<activeImages.size())
2690  {
2691  cropPano.setStacks(stackImgs);
2692  }
2693  cropPano.run();
2694  if (cropPano.hasRunSuccessfully())
2695  {
2696  newROI = cropPano.getResultOptimalROI();
2697  };
2698  };
2699 
2700  //set the ROI - fail if the right/bottom is zero, meaning all zero
2701  if(!newROI.isEmpty())
2702  {
2704  opt.setROI(newROI);
2707  );
2708  }
2709 }
2710 
2711 void GLPreviewFrame::OnAutocropOutside(wxCommandEvent& e)
2712 {
2713  DEBUG_INFO("Dirty ROI Calc\n");
2714  if (m_pano.getActiveImages().empty())
2715  {
2716  return;
2717  };
2718 
2719  vigra::Rect2D newROI;
2720  {
2721  ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2722  HuginBase::CalculateOptimalROIOutside cropPano(m_pano, &progress);
2723  cropPano.run();
2724  if (cropPano.hasRunSuccessfully())
2725  {
2726  newROI = cropPano.getResultOptimalROI();
2727  };
2728  };
2729 
2730  //set the ROI - fail if the right/bottom is zero, meaning all zero
2731  if (!newROI.isEmpty())
2732  {
2734  opt.setROI(newROI);
2737  );
2738  }
2739 }
2740 
2741 void GLPreviewFrame::OnFullScreen(wxCommandEvent & e)
2742 {
2743  ShowFullScreen(!IsFullScreen(), wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION);
2744 };
2745 
2746 void GLPreviewFrame::SetMode(int newMode)
2747 {
2748  if(m_mode==newMode)
2749  return;
2750  SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2751  switch(m_mode)
2752  {
2753  case mode_assistant:
2754  case mode_preview:
2755  // switch off identify and show cp tool
2756  identify_tool->setConstantOn(false);
2760  m_colorpicker_togglebutton->SetValue(false);
2761 // preview_helper->DeactivateTool(identify_tool);
2762 // panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2763 // plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2765  m_editCP_togglebutton->SetValue(false);
2766 
2768  m_identify_togglebutton->SetValue(false);
2772  XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2773  break;
2774  case mode_layout:
2775  // disable layout mode.
2779  // reactivate identify and camera tool when leaving layout mode
2784  m_GLPreview->SetLayoutMode(false);
2785  m_GLOverview->SetLayoutMode(false);
2786  // Switch the panorama mask back on.
2788  //restore blend mode
2790  updateBlendMode();
2791  break;
2792  case mode_projection:
2794  break;
2795  case mode_drag:
2799  if (individualDragging()) {
2800  std::vector<wxCheckBox*>::iterator it;
2801  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2802  (*it)->Show(false);
2803  }
2804  }
2805  break;
2806  case mode_crop:
2810  break;
2811  };
2812  m_mode=newMode;
2813  wxScrollEvent dummy;
2814  switch(m_mode)
2815  {
2816  case mode_assistant:
2817  case mode_preview:
2818  break;
2819  case mode_layout:
2820  //save blend mode setting, set to normal for layout mode
2821  non_layout_blend_mode=m_BlendModeChoice->GetSelection();
2822  m_BlendModeChoice->SetSelection(0);
2823  updateBlendMode();
2824  // turn off things not used in layout mode.
2827  // deactivate identify tool in layout mode
2831  m_GLPreview->SetLayoutMode(true);
2832  m_GLOverview->SetLayoutMode(true);
2836  // we need to update the meshes after switch to layout mode
2837  // otherwise the following update of scale has no meshes to scale
2838  m_GLPreview->Update();
2839  m_GLOverview->Update();
2840  OnLayoutScaleChange(dummy);
2841  break;
2842  case mode_projection:
2844  break;
2845  case mode_drag:
2849  if (individualDragging()) {
2850  std::vector<wxCheckBox*>::iterator it;
2851  for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2852  (*it)->Show(true);
2853  }
2854  }
2855  break;
2856  case mode_crop:
2860  break;
2861  };
2862  //enable group checkboxes only for drag mode tab
2864  m_GLPreview->Refresh();
2865 };
2866 
2867 void GLPreviewFrame::OnSelectMode(wxNotebookEvent &e)
2868 {
2869  if(m_mode!=-1)
2870  SetMode(e.GetSelection());
2871 };
2872 
2873 void GLPreviewFrame::OnToolModeChanging(wxNotebookEvent &e)
2874 {
2875  if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
2876  {
2877  wxBell();
2878  e.Veto();
2879  };
2880 };
2881 
2882 void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
2883 {
2885  long left, right, top, bottom;
2886  if (!m_ROITopTxt->GetValue().ToLong(&top)) {
2887  wxLogError(_("Top needs to be an integer bigger than 0"));
2888  return;
2889  }
2890  if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
2891  wxLogError(_("left needs to be an integer bigger than 0"));
2892  return;
2893  }
2894  if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
2895  wxLogError(_("right needs to be an integer bigger than 0"));
2896  return;
2897  }
2898  if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
2899  wxLogError(_("bottom needs to be an integer bigger than 0"));
2900  return;
2901  }
2902  opt.setROI(vigra::Rect2D(left, top, right, bottom));
2903  // make sure that left is really to the left of right
2904  if(opt.getROI().width()<1) {
2905  wxLogError(_("left boundary must be smaller than right"));
2907  return;
2908  }
2909  // make sure that top is really higher than bottom
2910  if(opt.getROI().height()<1) {
2911  wxLogError(_("top boundary must be smaller than bottom"));
2913  return;
2914  }
2915 
2918  );
2919 };
2920 
2921 void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
2922 {
2924  opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
2926 };
2927 
2928 void GLPreviewFrame::OnSetCropAspect(wxCommandEvent& e)
2929 {
2930  // ask user for a setting
2931  SelectAspectRatioDialog dlg(this);
2932  if (dlg.ShowModal() == wxID_OK)
2933  {
2935  const double aspectRatio = dlg.GetSelectedAspectRatio();
2936  // calculate the new ROI, move crop if necessary
2937  int left = opt.getROI().left();
2938  int top = opt.getROI().top();
2939  int width = opt.getROI().width();
2940  int height = opt.getROI().height();
2941  const int newHeight = 1.0 * width / aspectRatio;
2942  if (newHeight > height)
2943  {
2944  const int newWidth = 1.0 * height * aspectRatio;
2945  left = left + (width - newWidth) / 2.0;
2946  width = newWidth;
2947  }
2948  else
2949  {
2950  top = top + (height - newHeight) / 2.0;
2951  height = newHeight;
2952  };
2953  // finally set new crop
2954  opt.setROI(vigra::Rect2D(left, top, left + width, top + height));
2956  };
2957 }
2958 
2959 void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
2960 {
2962 
2963 
2964  wxString text = m_HFOVText->GetValue();
2965  DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
2966  if (text == wxEmptyString) {
2967  return;
2968  }
2969 
2970  double hfov;
2971  if (!hugin_utils::str2double(text, hfov)) {
2972  wxLogError(_("Value must be numeric."));
2973  return;
2974  }
2975 
2976  if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
2977  wxLogError(wxString::Format(
2978  _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
2979  opt.getMaxHFOV()));
2980  hfov=opt.getMaxHFOV();
2981  }
2982  opt.setHFOV(hfov);
2983  // recalculate panorama height...
2986  );
2987 
2988  DEBUG_INFO ( "new hfov: " << hfov )
2989 };
2990 
2991 void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
2992 {
2994 
2995  wxString text = m_VFOVText->GetValue();
2996  DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
2997  if (text == wxEmptyString) {
2998  return;
2999  }
3000 
3001  double vfov;
3002  if (!hugin_utils::str2double(text, vfov)) {
3003  wxLogError(_("Value must be numeric."));
3004  return;
3005  }
3006 
3007  if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
3008  wxLogError(wxString::Format(
3009  _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
3010  opt.getMaxVFOV()));
3011  vfov = opt.getMaxVFOV();
3012  }
3013  opt.setVFOV(vfov);
3014  // recalculate panorama height...
3017  );
3018 
3019  DEBUG_INFO ( "new vfov: " << vfov )
3020 };
3021 
3023 {
3024  if(m_mode==mode_layout)
3025  {
3026  double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
3027  m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
3028  m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
3029  m_GLPreview->Refresh();
3030  m_GLOverview->Refresh();
3031  };
3032 };
3033 
3035 {
3037  double hfov = opts.getHFOV();
3038  double vfov = opts.getVFOV();
3039  double maxfov = hfov > vfov ? hfov : vfov;
3040  wxString message;
3041  // If this is set to true, offer rectilinear as an alternative if it fits.
3042  bool rectilinear_option = false;
3043  switch (opts.getProjection()) {
3045  if (maxfov > 120.0) {
3046  // wide rectilinear image
3047  message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
3048  if (vfov < 110) {
3049  message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
3050  } else {
3051  message += _("For a very wide panorama, try equirectangular projection instead.");
3052  }
3053  message += " ";
3054  message += _("You could also try Panini projection.");
3055  }
3056  break;
3058  if (vfov > 120.0) {
3059  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.");
3060  } else rectilinear_option = true;
3061  break;
3063  if (vfov < 110.0 && hfov > 120.0)
3064  {
3065  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.");
3066  } else rectilinear_option = true;
3067  break;
3069  if (maxfov < 280.0) {
3070  rectilinear_option = true;
3071  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.");
3072  }
3073  break;
3075  if (maxfov > 300.0) {
3076  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.");
3077  } else rectilinear_option = true;
3078  break;
3079  default:
3080  rectilinear_option = true;
3081  }
3082  if (rectilinear_option && maxfov < 110.0) {
3083  message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
3084  }
3085  if (message.IsEmpty()) {
3086  // no message needed.
3087  m_infoBar->Dismiss();
3088  } else {
3089  m_infoBar->ShowMessage(message, wxICON_INFORMATION);
3090  }
3091 };
3092 
3094 {
3095  m_showProjectionHints=new_value;
3097  {
3098  m_infoBar->Dismiss();
3099  };
3100 };
3101 
3103 {
3104  hugin_utils::HuginMessageBox(_("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."),
3105  _("Hugin"), wxOK | wxICON_INFORMATION, this);
3106  wxConfigBase* cfg=wxConfigBase::Get();
3107  cfg->Write("/GLPreviewFrame/ShowProjectionHints", false);
3108  m_showProjectionHints=false;
3109  cfg->Flush();
3110  e.Skip();
3111 };
3112 
3113 void GLPreviewFrame::UpdateIdentifyTools(std::set<unsigned int> new_image_set)
3114 {
3115  if(identify_tool)
3116  {
3117  identify_tool->UpdateWithNewImageSet(new_image_set);
3118  };
3120  {
3122  };
3124  {
3126  };
3127 }
3128 
3130  m_preview_background_color = XRCCTRL(*this, "preview_background", wxColourPickerCtrl)->GetColour();
3131  wxString c = m_preview_background_color.GetAsString(wxC2S_HTML_SYNTAX);
3132  wxConfigBase* cfg=wxConfigBase::Get();
3133  cfg->Write("/GLPreviewFrame/PreviewBackground", c);
3134  cfg->Flush();
3138  redrawPreview();
3139 }
3140 
3143 }
3144 
3145 void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
3146 {
3147  if(preview_guide_tool)
3148  {
3149  int selection=e.GetSelection();
3151  //synchronize wxChoice in projection and crop tab
3152  m_GuideChoiceCrop->SetSelection(selection);
3153  m_GuideChoiceProj->SetSelection(selection);
3154  m_GuideChoiceDrag->SetSelection(selection);
3155  redrawPreview();
3156  };
3157 };
3158 
3160 {
3161  int old_selection=m_DragModeChoice->GetSelection();
3162  if(old_selection==wxNOT_FOUND)
3163  {
3164  old_selection=0;
3165  };
3166  m_DragModeChoice->Clear();
3167  m_DragModeChoice->Append(_("normal"));
3168  m_DragModeChoice->Append(_("normal, individual"));
3169  if(newLevel==GUI_EXPERT)
3170  {
3171  m_DragModeChoice->Append(_("mosaic"));
3172  m_DragModeChoice->Append(_("mosaic, individual"));
3173  m_DragModeChoice->SetSelection(old_selection);
3174  }
3175  else
3176  {
3177  if(old_selection>1)
3178  {
3179  m_DragModeChoice->SetSelection(old_selection-2);
3180  }
3181  else
3182  {
3183  m_DragModeChoice->SetSelection(old_selection);
3184  };
3185  };
3186  DragChoiceLayout(m_DragModeChoice->GetSelection());
3187  wxCommandEvent dummy;
3188  OnDragChoice(dummy);
3189 
3190  old_selection=m_OverviewModeChoice->GetSelection();
3191  m_OverviewModeChoice->Clear();
3192  m_OverviewModeChoice->Append(_("Panosphere (outside)"));
3193  m_OverviewModeChoice->Append(_("Panosphere (inside)"));
3194  if(newLevel==GUI_EXPERT)
3195  {
3196  m_OverviewModeChoice->Append(_("Mosaic plane"));
3197  };
3198  if(newLevel==GUI_EXPERT && old_selection==2)
3199  {
3200  m_OverviewModeChoice->SetSelection(2);
3201  }
3202  else
3203  {
3205  m_OverviewModeChoice->SetSelection(0);
3206  };
3207  if(newLevel==GUI_SIMPLE)
3208  {
3209 #ifdef __WXMAC__
3210  wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
3211 #endif
3212  if(m_guiLevel!=GUI_SIMPLE)
3213  {
3214  GetMenuBar()->Remove(0);
3215  GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
3216  };
3217  SetTitle(MainFrame::Get()->GetTitle());
3218  }
3219  else
3220  {
3221 #ifdef __WXMAC__
3222  wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
3223 #endif
3224  if(m_guiLevel==GUI_SIMPLE)
3225  {
3226  GetMenuBar()->Remove(0);
3227  GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
3228  };
3229  SetTitle(_("Fast Panorama preview"));
3230  };
3231  m_guiLevel=newLevel;
3232  // update menu items
3233  switch(m_guiLevel)
3234  {
3235  case GUI_SIMPLE:
3236  GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
3237  break;
3238  case GUI_ADVANCED:
3239  GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
3240  break;
3241  case GUI_EXPERT:
3242  GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
3243  break;
3244  };
3245 };
3246 
3247 void GLPreviewFrame::AddUserDefinedSequence(int id, const wxString& desc, const wxString& help)
3248 {
3249  if (id == -1)
3250  {
3251  m_createButton->GetSplitButtonMenu()->AppendSeparator();
3252  }
3253  else
3254  {
3255  m_createButton->GetSplitButtonMenu()->Append(id, desc, help);
3256  };
3257 };
3258 
3259 void GLPreviewFrame::AddUserDefinedAssistant(int id, const wxString& desc, const wxString& help)
3260 {
3261  if (id == -1)
3262  {
3263  m_alignButton->GetSplitButtonMenu()->AppendSeparator();
3264  }
3265  else
3266  {
3267  m_alignButton->GetSplitButtonMenu()->Append(id, desc, help);
3268  };
3269 };
3270 
3271 void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
3272 {
3273  MainFrame::Get()->Show();
3274  MainFrame::Get()->Raise();
3275 };
3276 
3277 void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
3278 {
3279  Close();
3280 };
3281 
3283 {
3284  if (wxConfig::Get()->Read("/ShowFisheyeCropHint", 1l) == 1)
3285  {
3286  // show hint about crop and open tab when requested
3287  wxDialog dlg;
3288  wxXmlResource::Get()->LoadDialog(&dlg, NULL, "fisheye_show_crop_dlg");
3289  if (dlg.ShowModal() == wxID_OK)
3290  {
3291  MainFrame::Get()->ShowMaskEditor(0, true);
3292  };
3293  if (XRCCTRL(dlg, "fisheye_crop_dont_ask_checkbox", wxCheckBox)->IsChecked())
3294  {
3295  wxConfig::Get()->Write("/ShowFisheyeCropHint", 0l);
3296  };
3297  };
3298 }
3299 
3300 void GLPreviewFrame::OnLoadImages(wxCommandEvent& e)
3301 {
3302  // load all images with default lens type
3303  LoadImages(-1);
3304 }
3305 
3306 void GLPreviewFrame::LoadImages(int preferredLensType)
3307 {
3308  // load the images.
3309  PanoOperation::AddImageOperation addImage(preferredLensType);
3310  HuginBase::UIntSet images;
3311  PanoCommand::PanoCommand* cmd=addImage.GetCommand(wxGetActiveWindow(), m_pano, images, m_guiLevel);
3312  if(cmd==NULL)
3313  {
3314  return;
3315  }
3316  //distribute images only if the existing images are not connected
3317  //otherwise it would destruct the existing image pattern
3318  const bool distributeImages=m_pano.getNrOfCtrlPoints()==0;
3319 
3320  const long autoAlign = wxConfigBase::Get()->Read("/Assistant/autoAlign", HUGIN_ASS_AUTO_ALIGN);
3321  if (autoAlign)
3322  {
3324  wxCommandEvent dummy;
3325  OnAlign(dummy);
3326  }
3327  else
3328  {
3329  std::vector<PanoCommand::PanoCommand*> cmds;
3330  cmds.push_back(cmd);
3331  if(distributeImages)
3332  {
3333  cmds.push_back(new PanoCommand::DistributeImagesCmd(m_pano));
3334  cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
3335  };
3337  combinedCmd->setName("add and distribute images");
3339  if(m_pano.getImage(0).isCircularCrop())
3340  {
3341  // show hint about crop for fisheye images
3342  // skip display if we read the information from our lens database
3343  HuginBase::FileMetaData metaData=m_pano.getImage(0).getFileMetadata();
3344  HuginBase::FileMetaData::const_iterator pos = metaData.find("readProjectionFromDB");
3345  if(!(pos != metaData.end() && pos->second == "true"))
3346  {
3348  };
3349  };
3350  };
3351 }
3352 
3353 void GLPreviewFrame::OnAlign( wxCommandEvent & e )
3354 {
3355  // run default assisant
3356  MainFrame::Get()->RunAssistant(this);
3357 }
3358 
3359 void GLPreviewFrame::OnCreate( wxCommandEvent & e )
3360 {
3361  PanoOutputDialog dlg(this, m_pano, m_guiLevel);
3362  if(dlg.ShowModal()==wxID_OK)
3363  {
3366  );
3367  wxCommandEvent dummy;
3368  MainFrame::Get()->OnDoStitch(dummy);
3369  };
3370 }
3371 
3372 // remove cp, relatively easy, we get the selected cp from the edit cp tool
3373 void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
3374 {
3377  // ask user, if pano should be optimized
3378  long afterEditCPAction = wxConfig::Get()->Read("/EditCPAfterAction", 0l);
3379  bool optimize = false;
3380  if (afterEditCPAction == 0)
3381  {
3382  wxDialog dlg;
3383  wxXmlResource::Get()->LoadDialog(&dlg, this, "edit_cp_optimize_dialog");
3384  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())));
3385  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3386  dlg.Fit();
3387  optimize = (dlg.ShowModal() == wxID_OK);
3388  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3389  {
3390  if (optimize)
3391  {
3392  wxConfig::Get()->Write("/EditCPAfterAction", 1l);
3393  }
3394  else
3395  {
3396  wxConfig::Get()->Write("/EditCPAfterAction", 2l);
3397  };
3398  };
3399  }
3400  else
3401  {
3402  optimize = (afterEditCPAction == 1);
3403  }
3404  if (optimize)
3405  {
3406  // invoke optimization routine
3407  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3408  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3409  };
3410 };
3411 
3412 // some helper for cp generation
3413 // maximal width for remapping for cp generating
3414 #define MAX_DIMENSION 1600
3416 {
3417  size_t imgNr;
3418  vigra::BRGBImage image;
3419  vigra::BImage mask;
3420 };
3421 
3422 typedef std::vector<FindStruct> FindVector;
3423 typedef std::multimap<double, vigra::Diff2D> MapPoints;
3424 
3426 
3427 void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
3428 {
3430  vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
3432  // some checking of conditions
3433  if (imgs.empty())
3434  {
3435  hugin_utils::HuginMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
3436  _("Hugin"), wxOK | wxICON_INFORMATION, this);
3437  return;
3438  };
3439  if (imgs.size() < 2)
3440  {
3441  hugin_utils::HuginMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
3442  _("Hugin"), wxOK | wxICON_INFORMATION, this);
3443  return;
3444  };
3445  if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
3446  {
3447  if (hugin_utils::HuginMessageBox(_("The selected rectangle is very big.\nThis function is only intended for smaller areas. Otherwise unwanted side effect can appear.\n\nProceed anyway?"),
3448  _("Hugin"), wxYES_NO | wxICON_INFORMATION, this) == wxNO)
3449  {
3450  return;
3451  };
3452  }
3454  opts.setROI(roi);
3455  // don't correct exposure
3456  opts.outputExposureValue = 0;
3457  // don't use GPU for remapping, this interfere with the fast preview window
3458  opts.remapUsingGPU = false;
3459  // rescale if size is too big
3460  if (roi.width() > MAX_DIMENSION)
3461  {
3462  opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
3463  roi = opts.getROI();
3464  };
3465  HuginBase::CPVector cps;
3466  {
3467  ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
3468  // remap all images to panorama projection
3469  FindVector cpInfos;
3470  HuginBase::CPVector tempCps;
3471  for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
3472  {
3473  const size_t imgNr = *it;
3474  if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
3475  {
3476  return;
3477  };
3478  FindStruct findStruct;
3479  findStruct.imgNr = imgNr;
3480  // remap image to panorama projection
3481  ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
3482 
3484  HuginBase::SrcPanoImage srcImg = m_pano.getSrcImage(imgNr);
3485  // don't correct exposure
3486  srcImg.setExposureValue(0);
3487  remapped->setPanoImage(srcImg, opts, roi);
3488  remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
3489  if (!progress.updateDisplay())
3490  {
3491  delete remapped;
3492  return;
3493  };
3494  findStruct.image = remapped->m_image;
3495  findStruct.mask = remapped->m_mask;
3496  delete remapped;
3497  cpInfos.push_back(findStruct);
3498  };
3499  if (cpInfos.size() > 1)
3500  {
3501  // match keypoints in all image pairs
3502  // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
3503  unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
3504  if (gridx < 1)
3505  {
3506  gridx = 1;
3507  }
3508  unsigned gridy = hugin_utils::roundi(25 / gridx);
3509  if (gridy < 1)
3510  {
3511  gridy = 1;
3512  }
3513  while (roi.width() / gridx < 20 && gridx > 1)
3514  {
3515  --gridx;
3516  };
3517  while (roi.height() / gridy < 20 && gridy > 1)
3518  {
3519  --gridy;
3520  };
3521  // template width
3522  const long templWidth = 20;
3523  // search width
3524  const long sWidth = 100;
3525  // match all images with all
3526  for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
3527  {
3528  if (!progress.updateDisplayValue(_("Matching interest points...")))
3529  {
3530  return;
3531  };
3532  vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
3533  // create a number of sub-regions
3534  std::vector<vigra::Rect2D> rects;
3535  for (unsigned party = 0; party < gridy; party++)
3536  {
3537  for (unsigned partx = 0; partx < gridx; partx++)
3538  {
3539  vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
3540  (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
3541  rect &= vigra::Rect2D(size);
3542  if (rect.width()>0 && rect.height()>0)
3543  {
3544  rects.push_back(rect);
3545  };
3546  };
3547  };
3548 
3549  if (!progress.updateDisplay())
3550  {
3551  return;
3552  };
3553 
3554 #pragma omp parallel for schedule(dynamic)
3555  for (int i = 0; i < rects.size(); ++i)
3556  {
3557  MapPoints points;
3558  vigra::Rect2D rect(rects[i]);
3559  // run interest point detection in sub-region
3560  vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
3561  //check if all points are inside the given image
3562  MapPoints validPoints;
3563  for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
3564  {
3565  if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
3566  {
3567  validPoints.insert(*it);
3568  };
3569  };
3570 
3571  if (!validPoints.empty())
3572  {
3573  // now fine-tune the interest points with all other images
3574  for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
3575  {
3576  unsigned nGood = 0;
3577  // loop over all points, starting with the highest corner score
3578  for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
3579  {
3580  if (nGood >= 2)
3581  {
3582  // we have enough points, stop
3583  break;
3584  }
3585  //check if point is covered by second image
3586  if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
3587  {
3588  continue;
3589  };
3590  // finally fine-tune point
3591  vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
3592  cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
3593  if (res.maxi < 0.9)
3594  {
3595  continue;
3596  }
3597  nGood++;
3598  // add control point
3599  {
3600  hugin_omp::ScopedLock sl(cpLock);
3601  tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
3602  cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
3603  };
3604  };
3605  };
3606  };
3607  };
3608  // free memory
3609  cpInfos[img1].image.resize(0, 0);
3610  cpInfos[img1].mask.resize(0, 0);
3611  };
3612 
3613  // transform coordinates back to image space
3614  for (size_t i = 0; i < tempCps.size(); ++i)
3615  {
3616  HuginBase::ControlPoint cp = tempCps[i];
3617  hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
3618  hugin_utils::FDiff2D p1Img;
3619  HuginBase::PTools::Transform transform;
3620  transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
3621  if (transform.transformImgCoord(p1Img, p1))
3622  {
3623  hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
3624  hugin_utils::FDiff2D p2Img;
3625  transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
3626  if (transform.transformImgCoord(p2Img, p2))
3627  {
3628  cp.x1 = p1Img.x;
3629  cp.y1 = p1Img.y;
3630  cp.x2 = p2Img.x;
3631  cp.y2 = p2Img.y;
3632  cps.push_back(cp);
3633  };
3634  };
3635  };
3636 
3637  if (!cps.empty())
3638  {
3639  // check newly found control points
3640  // create copy
3642  // remove all cps and set only the new found cp
3643  copyPano.setCtrlPoints(cps);
3644  // now create a subpano with only the selected images
3645  HuginBase::Panorama subPano = copyPano.getSubset(imgs);
3646  // clean control points
3647  if (!progress.updateDisplayValue(_("Checking results...")))
3648  {
3649  return;
3650  };
3652  HuginBase::UIntSet invalidCP = HuginBase::getCPoutsideLimit(subPano);
3654  if (!invalidCP.empty())
3655  {
3656  for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
3657  {
3658  cps.erase(cps.begin() + *it);
3659  };
3660  }
3661  // force closing progress dialog
3662  if (!progress.updateDisplayValue())
3663  {
3664  return;
3665  };
3667  // ask user, if pano should be optimized
3668  long afterEditCPAction = wxConfig::Get()->Read("/EditCPAfterAction", 0l);
3669  bool optimize = false;
3670  if (afterEditCPAction == 0)
3671  {
3672  // close progress window, otherwise the dialog don't autoamtically get the focus
3673  wxYield();
3674  wxDialog dlg;
3675  wxXmlResource::Get()->LoadDialog(&dlg, this, "edit_cp_optimize_dialog");
3676  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())));
3677  XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3678  dlg.Fit();
3679  optimize = (dlg.ShowModal() == wxID_OK);
3680  if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3681  {
3682  if (optimize)
3683  {
3684  wxConfig::Get()->Write("/EditCPAfterAction", 1l);
3685  }
3686  else
3687  {
3688  wxConfig::Get()->Write("/EditCPAfterAction", 2l);
3689  };
3690  };
3691  }
3692  else
3693  {
3694  optimize = (afterEditCPAction == 1);
3695  }
3696  if (optimize)
3697  {
3698  // invoke optimization routine
3699  wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3700  MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3701  };
3702  };
3703  };
3704  };
3705  // finally redraw
3706  m_GLPreview->Update();
3707  m_GLPreview->Refresh();
3708 };
3709 
3710 void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
3711 {
3712  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 0l);
3714 };
3715 
3716 void GLPreviewFrame::OnSelectMedianMenu(wxCommandEvent& e)
3717 {
3718  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 1l);
3720 };
3721 
3723 {
3724  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 2l);
3726 };
3727 
3729 {
3730  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 3l);
3732 };
3733 
3735 {
3736  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllKeepSelection", true);
3737  m_selectKeepSelection = true;
3738 };
3739 
3741 {
3742  wxConfig::Get()->Write("/GLPreviewFrame/SelectAllKeepSelection", false);
3743  m_selectKeepSelection = false;
3744 };
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:2376
void registerPTWXDlgFcn()
Definition: PTWXDlg.cpp:178
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:185
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:651
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:2129
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:46
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
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)
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:2000
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 StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Definition: wxutils.cpp:135
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:1651
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:84
static T min(T x, T y)
Definition: svm.cpp:62
HuginBase::UIntSet imageDragGroup
void OnNumTransform(wxCommandEvent &e)
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition: wxutils.cpp:176
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 RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename)
Definition: wxutils.cpp:67
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