Hugin trunk 0.1
Loading...
Searching...
No Matches
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
52
55#include "hugin/huginApp.h"
56#include "hugin/MainFrame.h"
57#include "hugin/ImagesPanel.h"
59#include "hugin/GLViewer.h"
61#include "hugin/PanoOperation.h"
64#include "base_wx/PTWXDlg.h"
69
70extern "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"
81#include "PreviewPanoMaskTool.h"
85#include "PreviewGuideTool.h"
86#include "PreviewEditCPTool.h"
87
88#include "ProjectionGridTool.h"
90
91#include "OverviewCameraTool.h"
93
94#include <wx/progdlg.h>
95#include <wx/infobar.h>
96
97// a random id, hope this doesn't break something..
98enum {
113
115enum{
123
124//------------------------------------------------------------------------------
125#define PF_STYLE (wxMAXIMIZE_BOX | wxMINIMIZE_BOX | wxRESIZE_BORDER | wxSYSTEM_MENU | wxCAPTION | wxCLOSE_BOX | wxCLIP_CHILDREN)
126
128{
129 DEBUG_DEBUG("CREATING FLOATING FRAME");
132 DEBUG_DEBUG("CREATED FLOATING FRAME");
133 return fl_frame;
134}
135
137 wxAuiFloatingFrame(parent, (wxAuiManager*)owner_mgr, pane, id, style)
138{
140}
141
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
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
186 crop_tool = NULL;
187 drag_tool = NULL;
201#ifdef __WXGTK__
202 loadedLayout=false;
203#endif
204
205 m_mode = -1;
206 m_oldProjFormat = -1;
207 // add a status bar
209 int widths[3] = {-3, 150, 150};
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);
227 m_identify_togglebutton = XRCCTRL(*this, "preview_identify_toggle_button", wxToggleButton);
228 m_identify_togglebutton->SetBitmapMargins(0, 5);
230 m_colorpicker_togglebutton = XRCCTRL(*this, "preview_color_picker_toggle_button", wxToggleButton);
231 m_colorpicker_togglebutton->SetBitmapMargins(0, 5);
233 m_editCP_togglebutton = XRCCTRL(*this, "preview_edit_cp_toggle_button", wxToggleButton);
234 m_editCP_togglebutton->SetBitmapMargins(0, 5);
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"));
249
250 // initialize preview background color
251 wxString c = cfg->Read("/GLPreviewFrame/PreviewBackground",HUGIN_PREVIEW_BACKGROUND);
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
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
266 new wxStaticBox(toggle_panel, -1, _("displayed images")),
267 wxHORIZONTAL );
269
271 //Horizontal scroll bars only
272 m_ButtonPanel->SetScrollRate(10, 0);
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));
281 //m_selectAllButton->SetBitmapMargins(5, 0);
282 m_selectAllButton->LoadMenu("preview_select_menu");
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;
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));
314 select_none->SetBitmap(bitmapBundle, wxLEFT);
315 select_none->SetBitmapMargins(5,0);
317
321 panel->SetSizer(sizer);
324
325 m_topsizer->Add(tool_panel, 0, wxEXPAND | wxALL, 2);
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
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
359 flexSizer->AddGrowableCol(0);
360 flexSizer->AddGrowableRow(0);
361
362 //overview sizer
364
365
367 1, // not vertically stretchable
368 wxEXPAND | // horizontally stretchable
369 wxALL, // draw border all around
370 5); // border width
371
373 1, 180,
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"));
384 opt.setVFOV(e.GetInt());
386 }
387 );
388#ifdef __WXMAC__
391 opt.setVFOV(e.GetInt());
393 }
394 );
395#endif
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
409
411 1, 360,
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"));
423 opt.setHFOV(e.GetInt());
425 }
426 );
427#ifdef __WXMAC__
430 opt.setHFOV(e.GetInt());
432 }
433 );
434#endif
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));
451 m_VFOVText = XRCCTRL(*this, "pano_text_vfov" ,wxTextCtrl);
453 m_VFOVText->PushEventHandler(new TextKillFocusHandler(this));
455
456 m_ROILeftTxt = XRCCTRL(*this, "pano_val_roi_left", wxTextCtrl);
458 m_ROILeftTxt->PushEventHandler(new TextKillFocusHandler(this));
460
461 m_ROIRightTxt = XRCCTRL(*this, "pano_val_roi_right", wxTextCtrl);
463 m_ROIRightTxt->PushEventHandler(new TextKillFocusHandler(this));
465
466 m_ROITopTxt = XRCCTRL(*this, "pano_val_roi_top", wxTextCtrl);
468 m_ROITopTxt->PushEventHandler(new TextKillFocusHandler(this));
470
471 m_ROIBottomTxt = XRCCTRL(*this, "pano_val_roi_bottom", wxTextCtrl);
473 m_ROIBottomTxt->PushEventHandler(new TextKillFocusHandler(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);
486
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
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);
504
505 m_mgr->AddPane(preview_panel,
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,
520 ).Name("overview"
521 ).MinSize(300,200
522 ).CloseButton(false
524 ).Caption(_("Overview")
525 ).FloatingSize(100,100
526 ).FloatingPosition(500,500
527 ).Dockable(true
528 ).PinButton(
529 ).Left(
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
543 // event handler for first menu item with automatic lens type detection
545 m_loadImagesButton->GetSplitButtonMenu()->AppendSeparator();
546 // now add all lens types to menu
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
564 // event handler for first menu item - default align
566 m_alignButton->GetSplitButtonMenu()->AppendSeparator();
567 // provide help texts in the status bar, add the necessary event handlers
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
580 // event handler for first menu item
582 m_createButton->GetSplitButtonMenu()->AppendSeparator();
583 // provide help texts in the status bar, add the necessary event handlers
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 */
593 for(int n=0; n < nP; n++) {
595 if (panoProjectionFeaturesQuery(n, &proj)) {
596 wxString str2(proj.name, wxConvLocal);
598 }
599 }
600 m_ProjectionChoice->SetSelection(2);
602
604 // Blend mode
605 // remaining blend mode should be added after OpenGL context has been created
606 // see FillBlendMode()
608 // create choice item
609 m_BlendModeChoice = XRCCTRL(*this,"blend_mode_choice",wxChoice);
610 m_BlendModeChoice->Append(_("normal"));
611 m_BlendModeChoice->SetSelection(0);
613
614 m_DragModeChoice = XRCCTRL(*this, "drag_mode_choice", wxChoice);
616 bool individualDrag;
617 cfg->Read("/GLPreviewFrame/individualDragMode", &individualDrag, false);
619 {
620 m_DragModeChoice->SetSelection(1);
621 }
622 else
623 {
624 m_DragModeChoice->SetSelection(0);
625 };
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);
656
657 m_exposureTextCtrl = XRCCTRL(*this, "exposure_text", wxTextCtrl);
658 m_exposureTextCtrl->PushEventHandler(new TextKillFocusHandler(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()));
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);
679
681 wxArtProvider::GetBitmap(wxART_REDO));
682 resetProjButton->SetToolTip(_("Resets the projection's parameters to their default values."));
685
689
690 for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++) {
691
695 0, // not vertically strechable
696 wxLEFT | wxRIGHT, // draw border all around
697 5); // border width
700 m_projParamTextCtrl[i]->PushEventHandler(new TextKillFocusHandler(this));
703 0, // not vertically strechable
704 wxLEFT | wxRIGHT, // draw border all around
705 5); // border width
706
710#ifdef __WXMAC__
712#endif
714
716 1, // not vertically strechable
717 wxLEFT | wxRIGHT | wxALIGN_CENTER_VERTICAL , // draw border all around
718 5); // border width
719 }
720
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);
734#else
735 wxIcon myIcon(huginApp::Get()->GetXRCPath() + "data/hugin.png",wxBITMAP_TYPE_PNG);
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 // build context menu for images button
754 m_removeImageMenuId = m_imageMenu.Append(wxID_ANY, "Remove image")->GetId();
756
757 // bind event handlers
760 Bind(wxEVT_MENU_CLOSE, [this](wxMenuEvent& e) { m_GLPreview->Refresh(); e.Skip();});
761 Bind(wxEVT_SLIDER, &GLPreviewFrame::OnLayoutScaleChange, this, XRCID("layout_scale_slider"));
763 // handler for menu items
764 Bind(wxEVT_MENU, &GLPreviewFrame::OnOverviewToggle, this, XRCID("action_show_overview"));
765 Bind(wxEVT_MENU, &GLPreviewFrame::OnSwitchPreviewGrid, this, XRCID("action_show_grid"));
766 Bind(wxEVT_MENU, &GLPreviewFrame::OnFullScreen, this, XRCID("ID_SHOW_FULL_SCREEN_PREVIEW"));
767 Bind(wxEVT_MENU, &GLPreviewFrame::OnShowMainFrame, this, XRCID("action_show_main_frame"));
768 Bind(wxEVT_MENU, &GLPreviewFrame::OnUserExit, this, XRCID("action_exit_preview"));
769 // context menu of select all button
770 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectAllMenu, this, XRCID("selectMenu_selectAll"));
771 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectMedianMenu, this, XRCID("selectMenu_selectMedian"));
772 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectDarkestMenu, this, XRCID("selectMenu_selectBrightest"));
773 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectBrightestMenu, this, XRCID("selectMenu_selectDarkest"));
774 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectKeepSelection, this, XRCID("selectMenu_keepCurrentSelection"));
775 Bind(wxEVT_MENU, &GLPreviewFrame::OnSelectResetSelection, this, XRCID("selectMenu_resetSelection"));
776 // handler for different buttons
777 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnCenterHorizontally, this, XRCID("preview_center_tool"));
778 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnFitPano, this, XRCID("preview_fit_pano_tool"));
779 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnFitPano, this, XRCID("preview_fit_pano_tool2"));
780 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnStraighten, this, XRCID("preview_straighten_pano_tool"));
781 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnNumTransform, this, XRCID("apply_num_transform"));
782 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnAutocrop, this, XRCID("preview_autocrop_tool"));
783 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnStackAutocrop, this, XRCID("preview_stack_autocrop_tool"));
784 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnAutocropOutside, this, XRCID("preview_autocrop_outside_tool"));
785 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnResetCrop, this, XRCID("reset_crop_button"));
786 Bind(wxEVT_BUTTON, &GLPreviewFrame::OnSetCropAspect, this, XRCID("crop_aspect_button"));
787 //checkboxes
788 Bind(wxEVT_CHECKBOX, &GLPreviewFrame::OnPhotometric, this, XRCID("preview_photometric_tool"));
789 Bind(wxEVT_CHECKBOX, &GLPreviewFrame::OnControlPoint, this, XRCID("preview_control_point_tool"));
790 // process enter key in num transform boxes
791 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_yaw"));
792 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_pitch"));
793 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_roll"));
794 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_x"));
795 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_y"));
796 Bind(wxEVT_TEXT_ENTER, &GLPreviewFrame::OnNumTransform, this, XRCID("input_z"));
797
798 if (cfg->Read("/GLPreviewFrame/isShown", 0l) != 0)
799 {
800#if defined __WXMSW__ || defined __WXMAC__
801 InitPreviews();
802 Show();
803#else
804 Show();
806#endif
807 }
809#if defined __WXMAC__
810 Layout();
811 Update();
812#endif
813}
814
816{
817#ifdef __WXGTK__
818 if(loadedLayout)
819 {
820 return;
821 };
822 loadedLayout=true;
823#endif
824 wxString OpenGLLayout=wxConfig::Get()->Read("/GLPreviewFrame/OpenGLLayout");
825 if(!OpenGLLayout.IsEmpty())
826 {
827 m_mgr->LoadPerspective(OpenGLLayout,true);
828#ifdef __WXGTK__
829 if(!GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked())
830 {
831 wxAuiPaneInfo &inf = m_mgr->GetPane("overview");
832 if (inf.IsOk())
833 {
834 inf.Hide();
835 }
836 m_GLOverview->SetActive(false);
837 };
838 m_mgr->Update();
840 dummy.SetShow(true);
842#endif
843 };
845};
846
848{
849 wxConfigBase * cfg = wxConfigBase::Get();
850
851 hugin_utils::StoreFramePosition(this, "GLPreviewFrame");
852
853 if ( (!this->IsIconized()) && (! this->IsMaximized()) && this->IsShown()) {
854 cfg->Write("/GLPreviewFrame/isShown", 1l);
855 } else {
856 cfg->Write("/GLPreviewFrame/isShown", 0l);
857 }
858
859 cfg->Write("/GLPreviewFrame/blendMode", m_BlendModeChoice->GetSelection());
860 cfg->Write("/GLPreviewFrame/OpenGLLayout", m_mgr->SavePerspective());
861 cfg->Write("/GLPreviewFrame/overview_hidden", !(GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()));
862 cfg->Write("/GLPreviewFrame/showPreviewGrid", GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked());
863 cfg->Write("/GLPreviewFrame/individualDragMode", individualDragging());
864 cfg->Write("/GLPreviewFrame/guide",m_GuideChoiceProj->GetSelection());
865};
866
868{
869 DEBUG_TRACE("dtor writing config");
871
872 // delete all of the tools. When the preview is never used we never get an
873 // OpenGL context and therefore don't create the tools.
874 if (crop_tool)
875 {
887 }
898 }
906 }
907 m_exposureTextCtrl->PopEventHandler(true);
908 m_HFOVText->PopEventHandler(true);
909 m_rangeCompressionTextCtrl->PopEventHandler(true);
910 m_VFOVText->PopEventHandler(true);
911 m_ROILeftTxt->PopEventHandler(true);
912 m_ROIRightTxt->PopEventHandler(true);
913 m_ROITopTxt->PopEventHandler(true);
914 m_ROIBottomTxt->PopEventHandler(true);
915 for (int i=0; i < m_ToggleButtons.size(); i++)
916 {
917 m_ToggleButtons[i]->PopEventHandler(true);
918 m_GroupToggleButtons[i]->PopEventHandler(true);
919 }
920 for (int i=0; i < PANO_PROJECTION_MAX_PARMS; i++)
921 {
922 m_projParamTextCtrl[i]->PopEventHandler(true);
923 };
925
926 // deinitialize the frame manager
927 m_mgr->UnInit();
928 if (m_mgr) {
929 delete m_mgr;
930 }
932 {
933 delete m_filemenuSimple;
934 }
935 else
936 {
937 delete m_filemenuAdvanced;
938 };
939
940 DEBUG_TRACE("dtor end");
941}
942
952
957{
958 if (m_BlendModeChoice != NULL)
959 {
960 int index=m_BlendModeChoice->GetSelection();
961 if(index==0)
962 {
963 // normal mode
964 if (preview_helper != NULL
965 && difference_tool != NULL)
966 {
968 };
969
972 {
974 };
975
978 {
980 };
981
982
983 }
984 else
985 {
986 if(index==m_differenceIndex)
987 {
988 // difference mode
989 if (preview_helper != NULL
990 && identify_tool != NULL
991 && difference_tool != NULL )
992 {
994// preview_helper->DeactivateTool(identify_tool);
995 m_identify_togglebutton->SetValue(false);
998 };
999
1000 // difference mode
1004 {
1005// panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
1008 };
1009
1010 // difference mode
1014 {
1015// plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
1018 };
1019
1020 }
1021 else
1022 {
1023 DEBUG_WARN("Unknown blend mode selected");
1024 };
1025 }
1026 }
1027}
1028
1030{
1031 m_ROILeftTxt->ChangeValue(wxString::Format("%d", opts.getROI().left() ));
1032 m_ROIRightTxt->ChangeValue(wxString::Format("%d", opts.getROI().right() ));
1033 m_ROITopTxt->ChangeValue(wxString::Format("%d", opts.getROI().top() ));
1034 m_ROIBottomTxt->ChangeValue(wxString::Format("%d", opts.getROI().bottom() ));
1035
1036 // display the current aspect ratio
1037 if (opts.getROI().area() > 0)
1038 {
1039 const int commonDivisor = hugin_utils::gcd(opts.getROI().width(), opts.getROI().height());
1041 if (commonDivisor > std::pow(10, hugin_utils::floori(log10f(std::max(opts.getROI().width(), opts.getROI().height()))) - 2))
1042 {
1043 labelAspectRatio = wxString::Format("%d:%d", opts.getROI().width() / commonDivisor, opts.getROI().height() / commonDivisor);
1044 }
1045 else
1046 {
1047 const float ratio = 1.0f * opts.getROI().width() / opts.getROI().height();
1048 if (ratio > 1.0f)
1049 {
1050 labelAspectRatio=wxString::Format("%.2f:1", ratio);
1051 }
1052 else
1053 {
1054 labelAspectRatio=wxString::Format("1:%.2f", 1.0f / ratio);
1055 };
1056 };
1057 XRCCTRL(*this, "crop_aspect_label", wxStaticText)->SetLabel(labelAspectRatio);
1058 };
1059
1060};
1061
1063{
1065
1066 if(pano.getNrOfImages()==0)
1067 {
1068 m_createButton->Disable();
1069 XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("No images loaded."));
1070 }
1071 else
1072 {
1073 bool enableCreate = false;
1074 // check if images are at position 0
1075 for (size_t i = 0; i < pano.getNrOfImages(); ++i)
1076 {
1077 const HuginBase::SrcPanoImage& img = pano.getImage(i);
1078 if (img.getYaw() != 0.0 || img.getPitch() != 0.0 || img.getRoll() != 0.0)
1079 {
1080 enableCreate = true;
1081 break;
1082 };
1083 };
1084 // disable create button after loading images
1086 if (lastCmd == "add images" || lastCmd == "add and distribute images")
1087 {
1088 enableCreate = false;
1089 };
1090 if (!enableCreate && pano.getNrOfImages() == 1)
1091 {
1092 // some more checks for single image projects
1094 {
1095 enableCreate = true;
1096 };
1097 if (pano.getOptions().getROI() != vigra::Rect2D(pano.getOptions().getSize()))
1098 {
1099 enableCreate = true;
1100 };
1101 if (pano.getImage(0).getProjection() == HuginBase::SrcPanoImage::EQUIRECTANGULAR)
1102 {
1103 enableCreate = true;
1104 };
1105 };
1107 }
1108
1109 if (pano.getNrOfImages() > 1)
1110 {
1111 // in wxWidgets 2.9, format must have types that exactly match.
1112 // However std::size_t could be any unsiged integer, so we cast it to
1113 // unsigned long.int to be on the safe side.
1114 wxString alignMsg = wxString::Format(_("%lu images are connected by %lu control points.\n"), (unsigned long int) pano.getNrOfImages(), (unsigned long int) pano.getCtrlPoints().size());
1115
1116 if (m_pano.getNrOfCtrlPoints() > 0)
1117 {
1118 // find components..
1120 const HuginGraph::ImageGraph::Components comps = graph.GetComponents();
1121 if (comps.size() > 1)
1122 {
1123 alignMsg += wxString::Format(_("%lu unconnected image groups found: %s\n"), static_cast<unsigned long int>(comps.size()), Components2Str(comps).c_str());
1124 }
1125 else
1126 {
1128 {
1129 alignMsg += _("Images or control points have changed, new alignment is needed.");
1130 }
1131 else
1132 {
1133 HuginBase::CalculateCPStatisticsError calcStats(m_pano, MainFrame::Get()->GetOptimizeOnlyActiveImages(), MainFrame::Get()->GetOptimizeIgnoreLineCp());
1134 calcStats.run();
1135 const double max = calcStats.getResultMax();
1136 const double mean = calcStats.getResultMean();
1137
1138 if (max != 0.0)
1139 {
1140 alignMsg = alignMsg + wxString::Format(_("Mean error after optimization: %.1f pixel, max: %.1f"), mean, max);
1141 }
1142 }
1143 }
1144 }
1145 wxStaticText* statusCtrl = XRCCTRL(*this, "ass_status_text", wxStaticText);
1146 statusCtrl->SetLabel(alignMsg);
1147 statusCtrl->InvalidateBestSize();
1148 m_tool_notebook->GetPage(0)->Layout();
1149 Refresh();
1150 }
1151 else
1152 {
1153 if (pano.getNrOfImages() == 1)
1154 {
1155 XRCCTRL(*this, "ass_status_text", wxStaticText)->SetLabel(_("One image loaded."));
1156 };
1157 };
1158
1159 GetMenuBar()->Enable(XRCID("ID_EDITUNDO"), PanoCommand::GlobalCmdHist::getInstance().canUndo());
1160 GetMenuBar()->Enable(XRCID("ID_EDITREDO"), PanoCommand::GlobalCmdHist::getInstance().canRedo());
1161
1162 // TODO: update meaningful help text and dynamic links to relevant tabs
1163
1164 const HuginBase::PanoramaOptions & opts = pano.getOptions();
1165
1166 wxString projection;
1167 m_ProjectionChoice->SetSelection(opts.getProjection());
1168 m_VFOVSlider->Enable( opts.fovCalcSupported(opts.getProjection()) );
1169
1170 // No HDR display yet.
1171 /*
1172 m_outputModeChoice->SetSelection(opts.outputMode);
1173 if (opts.outputMode == PanoramaOptions::OUTPUT_HDR) {
1174 m_exposureTextCtrl->Hide();
1175 m_defaultExposureBut->Hide();
1176 m_decExposureBut->Hide();
1177 m_incExposureBut->Hide();
1178 } else {
1179 m_exposureTextCtrl->Show();
1180 m_defaultExposureBut->Show();
1181 m_decExposureBut->Show();
1182 m_incExposureBut->Show();
1183 }*/
1186
1187 const bool activeImgs = !pano.getActiveImages().empty();
1188
1189 // TODO: enable display of parameters and set their limits, if projection has some.
1190
1191 int nParam = opts.m_projFeatures.numberOfParameters;
1192 bool relayout = false;
1193 // if the projection format has changed
1194 if (opts.getProjection() != m_oldProjFormat) {
1195 DEBUG_DEBUG("Projection format changed");
1196 if (nParam) {
1197 // show parameters and update labels.
1198 m_projection_panel->GetSizer()->Show(m_projParamSizer, true, true);
1199 int i;
1200 for (i=0; i < nParam; i++) {
1201 const pano_projection_parameter * pp = & (opts.m_projFeatures.parm[i]);
1202 wxString str2(pp->name, wxConvLocal);
1204 m_projParamNamesLabel[i]->SetLabel(str2);
1205 m_projParamSlider[i]->SetRange(hugin_utils::roundi(pp->minValue), hugin_utils::roundi(pp->maxValue));
1206 }
1207 for(;i < PANO_PROJECTION_MAX_PARMS; i++) {
1208 m_projParamNamesLabel[i]->Hide();
1209 m_projParamSlider[i]->Hide();
1210 m_projParamTextCtrl[i]->Hide();
1211 }
1212 relayout = true;
1213 } else {
1214 m_projection_panel->GetSizer()->Show(m_projParamSizer, false, true);
1215 relayout = true;
1216 }
1217 }
1218 if (nParam) {
1219 // display new values
1220 std::vector<double> params = opts.getProjectionParameters();
1221 assert((int) params.size() == nParam);
1222 for (int i=0; i < nParam; i++) {
1224 m_projParamTextCtrl[i]->ChangeValue(wxString(val.wc_str(), wxConvLocal));
1226 }
1227 }
1228 if (relayout) {
1229 m_projection_panel->Layout();
1230 Refresh();
1231 }
1232 SetStatusText(wxString::Format("%.1f x %.1f", opts.getHFOV(), opts.getVFOV()),2);
1233 m_HFOVSlider->SetValue(hugin_utils::roundi(opts.getHFOV()));
1234 m_VFOVSlider->SetValue(hugin_utils::roundi(opts.getVFOV()));
1235 std::string val;
1236 val = hugin_utils::doubleToString(opts.getHFOV(),1);
1237 m_HFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1238 val = hugin_utils::doubleToString(opts.getVFOV(),1);
1239 m_VFOVText->ChangeValue(wxString(val.c_str(), wxConvLocal));
1240 m_VFOVText->Enable(opts.fovCalcSupported(opts.getProjection()));
1241
1243
1244 XRCCTRL(*this,"preview_autocrop_tool",wxButton)->Enable(activeImgs);
1245 XRCCTRL(*this,"preview_stack_autocrop_tool",wxButton)->Enable(activeImgs);
1246 UpdateRoiDisplay(opts);
1247
1249 {
1251 };
1252 redrawPreview();
1253}
1254
1256{
1257 DEBUG_TRACE("");
1258
1259 bool dirty = false;
1260
1261 unsigned int nrImages = pano.getNrOfImages();
1262 unsigned int nrButtons = m_ToggleButtons.size();
1263
1264 GetMenuBar()->Enable(XRCID("action_optimize"), nrImages > 0);
1265
1266// m_displayedImgs.clear();
1267
1268 // remove items for nonexisting images
1269 for (int i=nrButtons-1; i>=(int)nrImages; i--)
1270 {
1272 // Image toggle buttons have a event handler on the stack which
1273 // must be removed before the buttons get destroyed.
1274 m_ToggleButtons[i]->PopEventHandler();
1275 m_GroupToggleButtons[i]->PopEventHandler();
1276 delete m_ToggleButtons[i];
1277 delete m_GroupToggleButtons[i];
1278 delete m_ToggleButtonPanel[i];
1279 m_ToggleButtons.pop_back();
1280 m_GroupToggleButtons.pop_back();
1281 m_ToggleButtonPanel.pop_back();
1286 dirty = true;
1287 }
1288
1289 //change overview mode to panosphere if the translation plane parameter are non zero
1291 {
1293 {
1295 m_OverviewModeChoice->SetSelection(0);
1296 //check if drag mode is mosaic, if so reset to normal
1297 if(drag_tool)
1298 {
1300 {
1301 m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
1304 // adjust the layout
1305 DragChoiceLayout(m_DragModeChoice->GetSelection());
1306 };
1307 };
1308 }
1309 }
1310
1311 // add buttons
1312 if ( nrImages >= nrButtons ) {
1313 for(HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it){
1314 if (*it >= nrButtons) {
1315 // create new item.
1316// wxImage * bmp = new wxImage(sz.GetWidth(), sz.GetHeight());
1317 //put wxToggleButton in a wxPanel because
1318 //on Windows the background colour of wxToggleButton can't be changed
1319 wxPanel *pan = new wxPanel(m_ButtonPanel);
1321 pan->SetSizer(siz);
1323 ID_TOGGLE_BUT + *it,
1324 wxString::Format(" %d ",*it),
1328
1330
1331#if defined __WXMSW__ || defined __WXMAC__
1332 //we need a border around the button to see the colored panel
1333 //because changing backgroundcolor of wxToggleButton does not work in wxMSW
1334 siz->AddSpacer(5);
1336 siz->Add(but,0,wxLEFT | wxRIGHT | wxBOTTOM , 5);
1337#else
1338 siz->Add(but,0,wxALL ,0);
1339 siz->Add(butcheck, 0, wxALL | wxFIXED_MINSIZE, 0);
1340#endif
1341 // for the identification tool to work, we need to find when the
1342 // mouse enters and exits the button. We use a custom event
1343 // handler, which will also toggle the images:
1345 event_handler->AddIdentifyTool(&identify_tool);
1349 but->PushEventHandler(event_handler);
1350
1353 group_event_handler->AddDragTool((DragTool**) &drag_tool);
1355 group_event_handler->AddIdentifyTool(&identify_tool);
1359 butcheck->PushEventHandler(group_event_handler);
1361
1362 but->SetValue(true);
1363 m_ButtonSizer->Add(pan,
1364 0,
1365 wxLEFT | wxTOP,
1366 0);
1367 m_ToggleButtons.push_back(but);
1368 m_GroupToggleButtons.push_back(butcheck);
1369 m_ToggleButtonPanel.push_back(pan);
1370 dirty = true;
1371 }
1372 }
1373 }
1374
1375 // update existing items
1377 for (unsigned i=0; i < nrImages; i++) {
1379 wxFileName tFilename(wxString (pano.getImage(i).getFilename().c_str(), HUGIN_CONV_FILENAME));
1380 m_ToggleButtons[i]->SetToolTip(tFilename.GetFullName());
1381 }
1382
1383 if (dirty) {
1384 m_ButtonSizer->FitInside(m_ButtonPanel);
1385 Layout();
1386 SendSizeEvent();
1387 DEBUG_INFO("New m_ButtonPanel width: " << (m_ButtonPanel->GetSize()).GetWidth());
1388 DEBUG_INFO("New m_ButtonPanel Height: " << (m_ButtonPanel->GetSize()).GetHeight());
1389 }
1390 if(nrImages==0)
1391 {
1393 m_tool_notebook->ChangeSelection(mode_assistant);
1394 };
1395 for(size_t i=2; i<m_tool_notebook->GetPageCount();i++)
1396 {
1397 m_tool_notebook->GetPage(i)->Enable(nrImages!=0);
1398 };
1399 redrawPreview();
1400}
1401
1403{
1404 m_GLPreview->Refresh();
1405 m_GLOverview->Refresh();
1406}
1407
1416
1418{
1419
1420 DEBUG_TRACE("OnShow");
1421 bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1422 wxAuiPaneInfo &inf = m_mgr->GetPane("overview");
1423 if (inf.IsOk()) {
1424 if (e.IsShown()) {
1425 if (!inf.IsShown() && toggle_on ) {
1426 inf.Show();
1427 m_mgr->Update();
1428 }
1429 } else {
1430 if (inf.IsFloating() && inf.IsShown()) {
1431 DEBUG_DEBUG("hiding overview float");
1432 inf.Hide();
1433 m_mgr->Update();
1434 }
1435 }
1436 }
1437
1438}
1439
1440//the following methods are to substitude the GLViewer KeyUp and KeyDown methods
1441//so that tools use key events that happen globally to the preview frame
1442//however only key up event is sent, and not key down
1443//so until this is resolved they will remain to be handled by GLViewer
1445{
1446 if (preview_helper) {
1447 preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1448 }
1449 if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1452 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1453 }
1456 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), true);
1457 }
1458 }
1459
1460 }
1461 e.Skip();
1462}
1463
1465{
1466 if (preview_helper) {
1467 preview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1468 }
1469 if (GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked()) {
1472 plane_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1473 }
1474 }
1477 panosphere_overview_helper->KeypressEvent(e.GetKeyCode(), e.GetModifiers(), false);
1478 }
1479 }
1480
1481 }
1482 e.Skip();
1483}
1484
1485
1486
1488{
1489 DEBUG_TRACE("overview toggle");
1490 bool toggle_on = GetMenuBar()->FindItem(XRCID("action_show_overview"))->IsChecked();
1491 wxAuiPaneInfo &inf = m_mgr->GetPane("overview");
1492 if (inf.IsOk()) {
1493 if (inf.IsShown() && !toggle_on) {
1494 inf.Hide();
1495 m_GLOverview->SetActive(false);
1496 m_mgr->Update();
1497 } else if (!(inf.IsShown() && toggle_on)) {
1498 inf.Show();
1499#if defined __WXMSW__ || defined __WXMAC__
1500 m_GLOverview->SetActive(true);
1501 m_mgr->Update();
1502#else
1503 m_mgr->Update();
1504 m_GLOverview->SetActive(true);
1505#endif
1506 }
1507 }
1508}
1509
1525
1527{
1528 DEBUG_TRACE("OnClose")
1529 // do not close, just hide if we're not forced
1531 {
1532 if(!MainFrame::Get()->CloseProject(event.CanVeto(), MainFrame::CLOSE_PROGRAM))
1533 {
1534 if (event.CanVeto())
1535 {
1536 event.Veto();
1537 return;
1538 };
1539 };
1540 MainFrame::Get()->Close(true);
1541 }
1542 else
1543 {
1544 if (event.CanVeto())
1545 {
1546 event.Veto();
1547 Hide();
1548 DEBUG_DEBUG("hiding");
1549 }
1550 else
1551 {
1552 DEBUG_DEBUG("closing");
1553 this->Destroy();
1554 }
1555 };
1556}
1557
1558#if 0
1559// need to add the wxChoice somewhere
1560void PreviewFrame::OnProjectionChanged()
1561{
1562 PanoramaOptions opt = m_pano.getOptions();
1563 int lt = m_ProjectionChoice->GetSelection();
1564 wxString Ip;
1565 switch ( lt ) {
1566 case PanoramaOptions::RECTILINEAR: Ip = _("Rectilinear"); break;
1567 case PanoramaOptions::CYLINDRICAL: Ip = _("Cylindrical"); break;
1568 case PanoramaOptions::EQUIRECTANGULAR: Ip = _("Equirectangular"); break;
1569 }
1570 opt.projectionFormat = (PanoramaOptions::ProjectionFormat) lt;
1573 );
1574 DEBUG_DEBUG ("Projection changed: " << lt << ":" << Ip )
1575
1576
1577}
1578#endif
1579
1581{
1582 if (m_pano.getActiveImages().empty()) return;
1583
1584 // reset zoom so that full pano is visible
1588 );
1589}
1590
1591void GLPreviewFrame::OnStraighten(wxCommandEvent & e)
1592{
1593 if (m_pano.getNrOfImages() == 0) return;
1594
1597 );
1598}
1599
1600void GLPreviewFrame::OnFitPano(wxCommandEvent & e)
1601{
1602 if (m_pano.getActiveImages().empty()) return;
1603
1604 DEBUG_TRACE("");
1607 fitPano.run();
1608 opt.setHFOV(fitPano.getResultHorizontalFOV());
1609 opt.setHeight(hugin_utils::roundi(fitPano.getResultHeight()));
1610
1611 // reset zoom so that full pano is visible
1613
1616 );
1617
1618 DEBUG_INFO ( "new fov: [" << opt.getHFOV() << " "<< opt.getVFOV() << "] => height: " << opt.getHeight() );
1619}
1620
1621void GLPreviewFrame::OnShowAll(wxCommandEvent & e)
1622{
1623 if (m_pano.getNrOfImages() == 0) return;
1624
1627 {
1629 }
1630 else
1631 {
1633 {
1635 };
1636 std::vector<HuginBase::UIntVector> stackedImg = HuginBase::getSortedStacks(&m_pano);
1637 for (size_t i = 0; i < stackedImg.size(); ++i)
1638 {
1639 switch (m_selectAllMode)
1640 {
1642 displayedImgs.insert(*(stackedImg[i].rbegin()));
1643 break;
1645 displayedImgs.insert(*(stackedImg[i].begin()));
1646 break;
1648 default:
1649 displayedImgs.insert(stackedImg[i][stackedImg[i].size() / 2]);
1650 break;
1651 };
1652 };
1653 };
1656 );
1657}
1658
1659void GLPreviewFrame::OnShowNone(wxCommandEvent & e)
1660{
1661 if (m_pano.getNrOfImages() == 0) return;
1662
1664 for (unsigned int i=0; i < m_pano.getNrOfImages(); i++) {
1665 m_ToggleButtons[i]->SetValue(false);
1666 }
1670 );
1671}
1672
1673void GLPreviewFrame::OnNumTransform(wxCommandEvent & e)
1674{
1675 if (m_pano.getNrOfImages() == 0) return;
1676
1677 wxString text;
1678 double y;
1679 double p;
1680 double r;
1681 double x;
1682 double z;
1683
1684 int index = m_DragModeChoice->GetSelection();
1685 switch (index) {
1686 case 0: //normal
1687 case 1: //normal, individual
1688 //@TODO limit numeric transform to selected images
1689 text = XRCCTRL(*this,"input_yaw",wxTextCtrl)->GetValue();
1690 if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1691 {
1692 wxBell();
1693 hugin_utils::HuginMessageBox(_("Yaw value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1694 return;
1695 }
1696 text = XRCCTRL(*this,"input_pitch",wxTextCtrl)->GetValue();
1697 if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), p))
1698 {
1699 wxBell();
1700 hugin_utils::HuginMessageBox(_("Pitch value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1701 return;
1702 }
1703 text = XRCCTRL(*this,"input_roll",wxTextCtrl)->GetValue();
1704 if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), r))
1705 {
1706 wxBell();
1707 hugin_utils::HuginMessageBox(_("Roll value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1708 return;
1709 }
1712 );
1713 break;
1714 case 2: //mosaic
1715 case 3: //mosaic, individual
1716 //@TODO limit numeric transform to selected images
1717 text = XRCCTRL(*this,"input_x",wxTextCtrl)->GetValue();
1718 if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), x))
1719 {
1720 wxBell();
1721 hugin_utils::HuginMessageBox(_("X value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1722 return;
1723 }
1724 text = XRCCTRL(*this,"input_y",wxTextCtrl)->GetValue();
1725 if (!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), y))
1726 {
1727 wxBell();
1728 hugin_utils::HuginMessageBox(_("Y value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1729 return;
1730 }
1731 text = XRCCTRL(*this,"input_z",wxTextCtrl)->GetValue();
1732 if(!hugin_utils::stringToDouble(std::string(text.mb_str(wxConvLocal)), z))
1733 {
1734 wxBell();
1735 hugin_utils::HuginMessageBox(_("Z value must be numeric."), _("Hugin"), wxOK | wxICON_ERROR, this);
1736 return;
1737 }
1740 );
1741 break;
1742 }
1743}
1744
1746{
1748 // exposure
1749 wxString text = m_exposureTextCtrl->GetValue();
1750 DEBUG_INFO ("target exposure = " << text.mb_str(wxConvLocal) );
1751 double p = 0;
1752 if (text != wxEmptyString) {
1753 if (!hugin_utils::str2double(text, p)) {
1754 wxLogError(_("Value must be numeric."));
1755 return;
1756 }
1757 }
1758 opts.outputExposureValue = p;
1761 );
1762}
1763
1772
1781
1783{
1785 // range compression
1786 const wxString text = m_rangeCompressionTextCtrl->GetValue();
1787 if (!text.IsEmpty())
1788 {
1789 double p = 0;
1791 {
1792 wxLogError(_("Value must be numeric."));
1793 return;
1794 };
1795 if (p < 0 || p>20)
1796 {
1797 wxLogError(_("Value for range compression is outside of valid range."));
1798 return;
1799 };
1800 if (p != opts.outputRangeCompression)
1801 {
1802 opts.outputRangeCompression = p;
1805 );
1806 };
1807 };
1808}
1809
1810
1812{
1814 int nParam = opts.m_projFeatures.numberOfParameters;
1815 std::vector<double> para = opts.getProjectionParameters();
1816 for (int i = 0; i < nParam; i++) {
1817 if (e.GetEventObject() == m_projParamTextCtrl[i]) {
1818 wxString text = m_projParamTextCtrl[i]->GetValue();
1819 DEBUG_INFO ("param " << i << ": = " << text.mb_str(wxConvLocal) );
1820 double p = 0;
1821 if (text != wxEmptyString) {
1822 if (!hugin_utils::str2double(text, p)) {
1823 wxLogError(_("Value must be numeric."));
1824 return;
1825 }
1826 }
1827 para[i] = p;
1828 }
1829 }
1833 );
1834}
1835
1844
1846{
1848 const int nParam = opt.m_projFeatures.numberOfParameters;
1849 std::vector<double> para = opt.getProjectionParameters();
1850 for (int i = 0; i < nParam; i++)
1851 {
1852 if (e.GetEventObject() == m_projParamSlider[i])
1853 {
1854 // update
1855 para[i] = e.GetInt();
1856 break;
1857 }
1858 }
1859 opt.setProjectionParameters(para);
1860 opt.setHFOV(m_HFOVSlider->GetValue());
1861 opt.setVFOV(m_VFOVSlider->GetValue());
1863}
1864
1866{
1868 const int nParam = opt.m_projFeatures.numberOfParameters;
1869 std::vector<double> para = opt.getProjectionParameters();
1870 for (int i = 0; i < nParam; i++)
1871 {
1872 if (e.GetEventObject() == m_projParamSlider[i])
1873 {
1874 // update
1875 para[i] = e.GetInt();
1876 m_projParamTextCtrl[i]->ChangeValue(wxString::Format("%d", e.GetInt()));
1877 break;
1878 }
1879 }
1880 opt.setProjectionParameters(para);
1881 // we only actually update the panorama fully when the mouse is released.
1882 // As we are dragging it we don't want to create undo events, but we would
1883 // like to update the display, so we change the GLViewer's ViewState and
1884 // request a redraw.
1886 m_GLPreview->Refresh();
1887}
1888
1889void GLPreviewFrame::OnBlendChoice(wxCommandEvent & e)
1890{
1891 if (e.GetEventObject() == m_BlendModeChoice)
1892 {
1894 }
1895 else
1896 {
1897 // FIXME DEBUG_WARN("wxChoice event from unknown object received");
1898 }
1899}
1900
1901void GLPreviewFrame::OnDragChoice(wxCommandEvent & e)
1902{
1903 if (drag_tool)
1904 {
1906 int index = m_DragModeChoice->GetSelection();
1907 switch (index) {
1908 case 0: //normal
1909 case 1:
1911 break;
1912 case 2: //mosaic
1913 case 3:
1915 break;
1916 }
1918 {
1920 {
1921 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?"),
1922 _("Hugin"), wxYES_NO | wxICON_QUESTION, this) == wxYES)
1923 {
1925 }
1926 else
1927 {
1928 m_DragModeChoice->SetSelection(index-2);
1929 return;
1930 };
1931 };
1932 //switch overview mode to plane
1934 m_OverviewModeChoice->SetSelection(1);
1935 }
1936 else
1937 {
1938 //new mode is normal
1939 //set overview back to panosphere mode
1941 m_OverviewModeChoice->SetSelection(0);
1944 };
1945 //update drag mode
1948 // adjust the layout
1949 DragChoiceLayout(index);
1950 };
1951};
1952
1954{
1955 size_t nr = m_pano.getNrOfImages();
1956 for (size_t i = 0 ; i < nr; i++)
1957 {
1958 if (m_pano.getSrcImage(i).getTranslationPlaneYaw() != 0 ||
1959 m_pano.getSrcImage(i).getTranslationPlanePitch() != 0)
1960 {
1961 return true;
1962 };
1963 }
1964 return false;
1965};
1966
1968{
1969 HuginBase::UIntSet imgs;
1971 size_t nr = newPan.getNrOfImages();
1972 for (size_t i = 0 ; i < nr ; i++)
1973 {
1974 HuginBase::SrcPanoImage img = newPan.getSrcImage(i);
1975 img.setTranslationPlaneYaw(0);
1976 img.setTranslationPlanePitch(0);
1977 newPan.setSrcImage(i,img);
1978 imgs.insert(i);
1979 }
1982 );
1983};
1984
1986{
1988 if (newMode == 1)
1989 {
1991 }
1992 else
1993 {
1994 if (newMode == 2)
1995 {
1997 };
1998 };
2000 {
2001 return true;
2002 };
2004 {
2006 {
2008 return true;
2009 }
2010 else
2011 {
2012 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?"),
2013 _("Hugin"), wxYES_NO | wxICON_QUESTION, this) == wxYES)
2014 {
2017 return true;
2018 }
2019 else
2020 {
2021 return false;
2022 };
2023 };
2024 }
2025 else
2026 {
2028 return true;
2029 }
2030};
2031
2033{
2034 if(UpdateOverviewMode(m_OverviewModeChoice->GetSelection()))
2035 {
2038 //set drag mode to normal if new mode is panosphere mode
2040 {
2041 m_DragModeChoice->SetSelection(m_DragModeChoice->GetSelection()-2);
2042 OnDragChoice(e);
2043 };
2044 }
2045 else
2046 {
2047 //change mode was not successful or canceled by user, set mode choice back
2048 switch (m_GLOverview->GetMode())
2049 {
2051 m_OverviewModeChoice->SetSelection(0);
2052 break;
2054 m_OverviewModeChoice->SetSelection(1);
2055 break;
2056 case GLOverview::PLANE:
2057 m_OverviewModeChoice->SetSelection(2);
2058 break;
2059 };
2060 };
2061};
2062
2064{
2065 // visibility of controls based on selected drag mode
2066 bool normalMode=index==0 || index==1;
2067 XRCCTRL(*this,"label_yaw",wxStaticText)->Show(normalMode);
2068 XRCCTRL(*this,"input_yaw",wxTextCtrl)->Show(normalMode);
2069 XRCCTRL(*this,"label_pitch",wxStaticText)->Show(normalMode);
2070 XRCCTRL(*this,"input_pitch",wxTextCtrl)->Show(normalMode);
2071 XRCCTRL(*this,"label_roll",wxStaticText)->Show(normalMode);
2072 XRCCTRL(*this,"input_roll",wxTextCtrl)->Show(normalMode);
2073 XRCCTRL(*this,"label_x",wxStaticText)->Show(!normalMode);
2074 XRCCTRL(*this,"input_x",wxTextCtrl)->Show(!normalMode);
2075 XRCCTRL(*this,"label_y",wxStaticText)->Show(!normalMode);
2076 XRCCTRL(*this,"input_y",wxTextCtrl)->Show(!normalMode);
2077 XRCCTRL(*this,"label_z",wxStaticText)->Show(!normalMode);
2078 XRCCTRL(*this,"input_z",wxTextCtrl)->Show(!normalMode);
2079 // redraw layout to compress empty space
2080 XRCCTRL(*this,"apply_num_transform",wxButton)->GetParent()->Layout();
2081}
2082
2093
2102
2111
2112void GLPreviewFrame::OnProjectionChoice( wxCommandEvent & e )
2113{
2114 if (e.GetEventObject() == m_ProjectionChoice) {
2116 int lt = m_ProjectionChoice->GetSelection();
2117 wxString Ip;
2121 );
2122 DEBUG_DEBUG ("Projection changed: " << lt);
2123 m_projection_panel->Layout();
2124 Refresh();
2125 } else {
2126 // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2127 }
2128}
2129
2130/* We don't have an OpenGL hdr display yet
2131void GLPreviewFrame::OnOutputChoice( wxCommandEvent & e)
2132{
2133 if (e.GetEventObject() == m_outputModeChoice) {
2134 PanoramaOptions opt = m_pano.getOptions();
2135 int lt = m_outputModeChoice->GetSelection();
2136 wxString Ip;
2137 opt.outputMode = ( (PanoramaOptions::OutputMode) lt );
2138 PanoCommand::GlobalCmdHist::getInstance().addCommand(
2139 new PanoCommand::SetPanoOptionsCmd( m_pano, opt )
2140 );
2141
2142 } else {
2143 // FIXME DEBUG_WARN("wxChoice event from unknown object received");
2144 }
2145}
2146*/
2147
2152
2153void GLPreviewFrame::OnPhotometric(wxCommandEvent & e)
2154{
2155 m_GLPreview->SetPhotometricCorrect(e.IsChecked());
2156}
2157
2159{
2160 // create the tool objects.
2161 // we delay this until we have an OpenGL context so that they are free to
2162 // create texture objects and display lists before they are used.
2168 // bind corresponding menu events
2179
2181 if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2182 {
2184 };
2187
2188 // activate tools that are always active.
2190 // update the blend mode which activates some tools
2193 // update toolbar
2195}
2196
2198{
2205
2208
2210 if(GetMenuBar()->FindItem(XRCID("action_show_grid"))->IsChecked())
2211 {
2213 }
2214
2215
2219
2222
2223
2224
2225}
2226
2244
2245void GLPreviewFrame::OnIdentify(wxCommandEvent & e)
2246{
2247 SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2248 if (e.IsChecked())
2249 {
2250 m_BlendModeChoice->SetSelection(0);
2257// TurnOffTools(preview_helper->ActivateTool(identify_tool));
2258// TurnOffTools(panosphere_overview_helper->ActivateTool(panosphere_overview_identify_tool));
2259// TurnOffTools(plane_overview_helper->ActivateTool(plane_overview_identify_tool));
2260 } else {
2264// preview_helper->DeactivateTool(identify_tool);
2265// panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2266// plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2268 }
2269 m_GLPreview->Refresh();
2270 m_GLOverview->Refresh();
2271}
2272
2273void GLPreviewFrame::OnControlPoint(wxCommandEvent & e)
2274{
2275 if (!m_editCP_togglebutton->GetValue())
2276 {
2277 //process event only if edit cp tool is disabled
2278 SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2279 if (e.IsChecked())
2280 {
2284 }
2285 else {
2289 }
2290 m_GLPreview->Refresh();
2291 m_GLOverview->Refresh();
2292 };
2293}
2294
2296{
2297 std::set<Tool*>::iterator i;
2298 for (i = tools.begin(); i != tools.end(); ++i)
2299 {
2300 if (*i == crop_tool)
2301 {
2302 // cover up the guidelines
2303 m_GLPreview->Refresh();
2304 } else if (*i == drag_tool)
2305 {
2306 // cover up its boxes
2307 m_GLPreview->Refresh();
2308 } else if (*i == identify_tool)
2309 {
2310 // disabled the identify tool, toggle its button off.
2311 m_identify_togglebutton->SetValue(false);
2312 // cover up its indicators and restore normal button colours.
2313 m_GLPreview->Refresh();
2314 m_GLOverview->Refresh();
2316 } else if (*i == preview_control_point_tool)
2317 {
2318 // disabled the control point tool.
2319 XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2320 // cover up the control point lines.
2321 m_GLPreview->Refresh();
2322 m_GLOverview->Refresh();
2323 }
2324 }
2325}
2326
2328 unsigned char red,
2329 unsigned char green,
2330 unsigned char blue)
2331{
2332 // 0, 0, 0 indicates we want to go back to the system colour.
2333 // TODO: Maybe we should test this better on different themes.
2334#if defined __WXMSW__ || defined __WXMAC__
2335 if (red || green || blue)
2336 {
2337 // the identify tool wants us to highlight an image button in the given
2338 // colour, to match up with the display in the preview.
2339 // on windows change the color of the surhugin_utils::rounding wxPanel
2340 m_ToggleButtonPanel[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2341 }
2342 else
2343 {
2344 // return to the normal colour
2346 }
2347 m_ToggleButtonPanel[image_nr]->Refresh();
2348#else
2349 if (red || green || blue)
2350 {
2351 // change the color of the wxToggleButton
2352 m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_COLOUR);
2353 m_ToggleButtons[image_nr]->SetBackgroundColour(wxColour(red, green, blue));
2354 // black should be visible on the button's vibrant colours.
2355 m_ToggleButtons[image_nr]->SetForegroundColour(wxColour(0, 0, 0));
2356 }
2357 else
2358 {
2359 // return to the normal colour
2360 m_ToggleButtons[image_nr]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2361 m_ToggleButtons[image_nr]->SetBackgroundColour(wxNullColour);
2362 m_ToggleButtons[image_nr]->SetForegroundColour(wxNullColour);
2363 };
2364 m_ToggleButtons[image_nr]->Refresh();
2365#endif
2366}
2367
2369{
2370 // when we turn off the identification tool, any buttons that were coloured
2371 // to match the image in the preview should be given back the system themed
2372 // colours.
2373 unsigned int nr_images = m_pano.getNrOfImages();
2374 for (unsigned image = 0; image < nr_images; image++)
2375 {
2376#if defined __WXMSW__ || defined __WXMAC__
2377 m_ToggleButtonPanel[image]->SetBackgroundColour(m_ToggleButtonPanel[image]->GetParent()->GetBackgroundColour());
2378 m_ToggleButtonPanel[image]->Refresh();
2379#else
2380 m_ToggleButtons[image]->SetBackgroundStyle(wxBG_STYLE_SYSTEM);
2381 m_ToggleButtons[image]->SetBackgroundColour(wxNullColour);
2382 m_ToggleButtons[image]->SetForegroundColour(wxNullColour);
2383 m_ToggleButtons[image]->Refresh();
2384#endif
2385 }
2386}
2387
2388void GLPreviewFrame::OnColorPicker(wxCommandEvent &e)
2389{
2390 // blank status text as it refers to an old tool.
2392 if (e.IsChecked())
2393 {
2394 if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2395 {
2397 };
2398 // deactivate delete cp tool if active
2400 m_editCP_togglebutton->SetValue(false);
2402 }
2403 else
2404 {
2406 };
2407 m_GLPreview->Refresh();
2408};
2409
2411{
2414 );
2415 //now toggle button and deactivate tool
2416 m_colorpicker_togglebutton->SetValue(false);
2417 //direct deactivation of tool does not work because this function is called by the tool itself
2418 //so we are send an event to deactivate the tool
2419 wxCommandEvent e(wxEVT_TOGGLEBUTTON);
2420 e.SetInt(0);
2421 m_colorpicker_togglebutton->GetEventHandler()->AddPendingEvent(e);
2422};
2423
2424void GLPreviewFrame::OnEditCPTool(wxCommandEvent &e)
2425{
2426 // blank status text as it refers to an old tool.
2428 if (e.IsChecked())
2429 {
2430 // deactivate color picker tool
2432 m_colorpicker_togglebutton->SetValue(false);
2433 // show automatically all cp
2436 }
2437 else
2438 {
2439 if (!XRCCTRL(*this, "preview_control_point_tool", wxCheckBox)->GetValue())
2440 {
2442 };
2444 };
2445 m_GLPreview->Refresh();
2446};
2447
2461
2463{
2464 // When using the identify tool, we want to identify image locations when
2465 // the user moves the mouse over the image buttons, but only if the image
2466 // is being shown.
2467 if (
2468 m_identify_button->GetValue() &&
2470 {
2471 std::vector<PreviewIdentifyTool**>::iterator it;
2472 for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2473 (*(*it))->ShowImageNumber(image_number);
2474 }
2475 }
2476 e.Skip();
2477}
2478
2480{
2481 // if the mouse left one of the image toggle buttons with the identification
2482 // tool active, we should stop showing the image indicator for that button.
2483 if (
2484 m_identify_button->GetValue() &&
2486 {
2487 std::vector<PreviewIdentifyTool**>::iterator it;
2488 for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2489 (*(*it))->StopShowingImages();
2490 }
2491 }
2492 e.Skip();
2493}
2494
2496{
2497 // the user is turning on or off an image using its button. We want to turn
2498 // the indicators on and off if appropriate correctly to. We use OnEnter
2499 // and OnLeave for the indicators, but these only work when the image is
2500 // showing, so we are carefull of the order:
2501 HuginBase::UIntSet activeImages = m_pano->getActiveImages();
2503 if (e.IsChecked()) {
2504 activeImages.insert(image_number);
2506 new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2507 );
2509 } else {
2511 activeImages.erase(image_number);
2513 new PanoCommand::SetActiveImagesCmd(*m_pano, activeImages)
2514 );
2515 }
2516}
2517
2521
2529
2533
2534
2536{
2537 //mark the image
2538 if (m_pano->getActiveImages().count(image_number))
2539 {
2540 std::vector<PreviewIdentifyTool**>::iterator it;
2541 for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2542 (*(*it))->ShowImageNumber(image_number);
2543 }
2544 }
2545 e.Skip();
2546}
2547
2549{
2550 //unmark the image
2551 if (m_pano->getActiveImages().count(image_number))
2552 {
2553 std::vector<PreviewIdentifyTool**>::iterator it;
2554 for(it = identify_tools.begin() ; it != identify_tools.end() ; ++it) {
2555 (*(*it))->StopShowingImages();
2556 }
2557 }
2558 e.Skip();
2559}
2560
2562{
2564 if (e.IsChecked()) {
2567 } else {
2570 }
2571}
2572
2576
2578{
2579 return m_DragModeChoice->GetSelection()==1 ||
2580 m_DragModeChoice->GetSelection()==3;
2581}
2582
2584 if (imageDragGroup.count(image_nr) == 0) {
2585 this->AddImageToDragGroup(image_nr, update_check_box);
2586 } else {
2588 }
2589}
2591 imageDragGroup.erase(image_nr);
2592 if (update_check_box) {
2593 m_GroupToggleButtons[image_nr]->SetValue(false);
2594 }
2595}
2597 imageDragGroup.insert(image_nr);
2598 if (update_check_box) {
2599 m_GroupToggleButtons[image_nr]->SetValue(true);
2600 }
2601}
2604 std::vector<wxCheckBox*>::iterator it;
2605 unsigned int nr = 0;
2606 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2607 (*it)->SetValue(imageDragGroup.count(nr++)>0);
2608 }
2609}
2614 imageDragGroup.clear();
2615 std::vector<wxCheckBox*>::iterator it;
2616 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2617 (*it)->SetValue(false);
2618 }
2619}
2620
2622{
2623 std::vector<wxCheckBox*>::iterator it;
2624 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it)
2625 {
2626 (*it)->Show(isShown);
2627 }
2628 Layout();
2629};
2630
2633{
2635 m_differenceIndex=m_BlendModeChoice->Append(_("difference"));
2636 // update size
2637 m_BlendModeChoice->InvalidateBestSize();
2638 m_BlendModeChoice->GetParent()->Layout();
2639 Refresh();
2640 // get blend mode last state
2641 unsigned int oldMode = wxConfigBase::Get()->Read("/GLPreviewFrame/blendMode", 0l);
2642 // limit old state to max available states
2643 if (oldMode >= m_BlendModeChoice->GetCount())
2644 {
2645 oldMode = 0;
2646 }
2647 m_BlendModeChoice->SetSelection(oldMode);
2649};
2650
2651void GLPreviewFrame::OnAutocrop(wxCommandEvent &e)
2652{
2653 DEBUG_INFO("Dirty ROI Calc\n");
2654 if (m_pano.getActiveImages().empty())
2655 {
2656 return;
2657 };
2658
2659 vigra::Rect2D newROI;
2660 {
2661 ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2663 cropPano.run();
2664 if (cropPano.hasRunSuccessfully())
2665 {
2666 newROI = cropPano.getResultOptimalROI();
2667 };
2668 };
2669
2670 //set the ROI - fail if the right/bottom is zero, meaning all zero
2671 if(!newROI.isEmpty())
2672 {
2674 opt.setROI(newROI);
2677 );
2678 }
2679}
2680
2681void GLPreviewFrame::OnStackAutocrop(wxCommandEvent &e)
2682{
2683 DEBUG_INFO("Dirty ROI Calc\n");
2684 if (m_pano.getActiveImages().empty())
2685 {
2686 return;
2687 };
2688
2689 vigra::Rect2D newROI;
2690 {
2691 ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2692 HuginBase::UIntSet activeImages = m_pano.getActiveImages();
2693 std::vector<HuginBase::UIntSet> stackImgs = getHDRStacks(m_pano, activeImages, m_pano.getOptions());
2695 //only use hdr autocrop for projects with stacks
2696 //otherwise fall back to "normal" autocrop
2697 if (stackImgs.size()<activeImages.size())
2698 {
2699 cropPano.setStacks(stackImgs);
2700 }
2701 cropPano.run();
2702 if (cropPano.hasRunSuccessfully())
2703 {
2704 newROI = cropPano.getResultOptimalROI();
2705 };
2706 };
2707
2708 //set the ROI - fail if the right/bottom is zero, meaning all zero
2709 if(!newROI.isEmpty())
2710 {
2712 opt.setROI(newROI);
2715 );
2716 }
2717}
2718
2720{
2721 DEBUG_INFO("Dirty ROI Calc\n");
2722 if (m_pano.getActiveImages().empty())
2723 {
2724 return;
2725 };
2726
2727 vigra::Rect2D newROI;
2728 {
2729 ProgressReporterDialog progress(0, _("Autocrop"), _("Calculating optimal crop"), this);
2731 cropPano.run();
2732 if (cropPano.hasRunSuccessfully())
2733 {
2734 newROI = cropPano.getResultOptimalROI();
2735 };
2736 };
2737
2738 //set the ROI - fail if the right/bottom is zero, meaning all zero
2739 if (!newROI.isEmpty())
2740 {
2742 opt.setROI(newROI);
2745 );
2746 }
2747}
2748
2753
2755{
2756 if(m_mode==newMode)
2757 return;
2758 SetStatusText(wxEmptyString, 0); // blank status text as it refers to an old tool.
2759 switch(m_mode)
2760 {
2761 case mode_assistant:
2762 case mode_preview:
2763 // switch off identify and show cp tool
2768 m_colorpicker_togglebutton->SetValue(false);
2769// preview_helper->DeactivateTool(identify_tool);
2770// panosphere_overview_helper->DeactivateTool(panosphere_overview_identify_tool);
2771// plane_overview_helper->DeactivateTool(plane_overview_identify_tool);
2773 m_editCP_togglebutton->SetValue(false);
2774
2776 m_identify_togglebutton->SetValue(false);
2780 XRCCTRL(*this,"preview_control_point_tool",wxCheckBox)->SetValue(false);
2781 break;
2782 case mode_layout:
2783 // disable layout mode.
2787 // reactivate identify and camera tool when leaving layout mode
2792 m_GLPreview->SetLayoutMode(false);
2794 // Switch the panorama mask back on.
2796 //restore blend mode
2799 break;
2800 case mode_projection:
2802 break;
2803 case mode_drag:
2807 if (individualDragging()) {
2808 std::vector<wxCheckBox*>::iterator it;
2809 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2810 (*it)->Show(false);
2811 }
2812 }
2813 break;
2814 case mode_crop:
2818 break;
2819 };
2822 switch(m_mode)
2823 {
2824 case mode_assistant:
2825 case mode_preview:
2826 break;
2827 case mode_layout:
2828 //save blend mode setting, set to normal for layout mode
2830 m_BlendModeChoice->SetSelection(0);
2832 // turn off things not used in layout mode.
2835 // deactivate identify tool in layout mode
2844 // we need to update the meshes after switch to layout mode
2845 // otherwise the following update of scale has no meshes to scale
2846 m_GLPreview->Update();
2847 m_GLOverview->Update();
2849 break;
2850 case mode_projection:
2852 break;
2853 case mode_drag:
2857 if (individualDragging()) {
2858 std::vector<wxCheckBox*>::iterator it;
2859 for(it = m_GroupToggleButtons.begin() ; it != m_GroupToggleButtons.end() ; ++it) {
2860 (*it)->Show(true);
2861 }
2862 }
2863 break;
2864 case mode_crop:
2868 break;
2869 };
2870 //enable group checkboxes only for drag mode tab
2872 m_GLPreview->Refresh();
2873};
2874
2876{
2877 if(m_mode!=-1)
2878 SetMode(e.GetSelection());
2879};
2880
2882{
2883 if(m_pano.getNrOfImages()==0 && e.GetOldSelection()==0)
2884 {
2885 wxBell();
2886 e.Veto();
2887 };
2888};
2889
2890void GLPreviewFrame::OnROIChanged ( wxCommandEvent & e )
2891{
2893 long left, right, top, bottom;
2894 if (!m_ROITopTxt->GetValue().ToLong(&top)) {
2895 wxLogError(_("Top needs to be an integer bigger than 0"));
2896 return;
2897 }
2898 if (!m_ROILeftTxt->GetValue().ToLong(&left)) {
2899 wxLogError(_("left needs to be an integer bigger than 0"));
2900 return;
2901 }
2902 if (!m_ROIRightTxt->GetValue().ToLong(&right)) {
2903 wxLogError(_("right needs to be an integer bigger than 0"));
2904 return;
2905 }
2906 if (!m_ROIBottomTxt->GetValue().ToLong(&bottom)) {
2907 wxLogError(_("bottom needs to be an integer bigger than 0"));
2908 return;
2909 }
2910 opt.setROI(vigra::Rect2D(left, top, right, bottom));
2911 // make sure that left is really to the left of right
2912 if(opt.getROI().width()<1) {
2913 wxLogError(_("left boundary must be smaller than right"));
2915 return;
2916 }
2917 // make sure that top is really higher than bottom
2918 if(opt.getROI().height()<1) {
2919 wxLogError(_("top boundary must be smaller than bottom"));
2921 return;
2922 }
2923
2926 );
2927};
2928
2929void GLPreviewFrame::OnResetCrop(wxCommandEvent &e)
2930{
2932 opt.setROI(vigra::Rect2D(0,0,opt.getWidth(),opt.getHeight()));
2934};
2935
2936void GLPreviewFrame::OnSetCropAspect(wxCommandEvent& e)
2937{
2938 // ask user for a setting
2940 if (dlg.ShowModal() == wxID_OK)
2941 {
2943 const double aspectRatio = dlg.GetSelectedAspectRatio();
2944 // calculate the new ROI, move crop if necessary
2945 int left = opt.getROI().left();
2946 int top = opt.getROI().top();
2947 int width = opt.getROI().width();
2948 int height = opt.getROI().height();
2949 const int newHeight = 1.0 * width / aspectRatio;
2950 if (newHeight > height)
2951 {
2952 const int newWidth = 1.0 * height * aspectRatio;
2953 left = left + (width - newWidth) / 2.0;
2954 width = newWidth;
2955 }
2956 else
2957 {
2958 top = top + (height - newHeight) / 2.0;
2959 height = newHeight;
2960 };
2961 // finally set new crop
2962 opt.setROI(vigra::Rect2D(left, top, left + width, top + height));
2964 };
2965}
2966
2967void GLPreviewFrame::OnHFOVChanged ( wxCommandEvent & e )
2968{
2970
2971
2972 wxString text = m_HFOVText->GetValue();
2973 DEBUG_INFO ("HFOV = " << text.mb_str(wxConvLocal) );
2974 if (text == wxEmptyString) {
2975 return;
2976 }
2977
2978 double hfov;
2979 if (!hugin_utils::str2double(text, hfov)) {
2980 wxLogError(_("Value must be numeric."));
2981 return;
2982 }
2983
2984 if ( hfov <=0 || hfov > opt.getMaxHFOV()) {
2985 wxLogError(wxString::Format(
2986 _("Invalid HFOV value. Maximum HFOV for this projection is %lf."),
2987 opt.getMaxHFOV()));
2988 hfov=opt.getMaxHFOV();
2989 }
2990 opt.setHFOV(hfov);
2991 // recalculate panorama height...
2994 );
2995
2996 DEBUG_INFO ( "new hfov: " << hfov )
2997};
2998
2999void GLPreviewFrame::OnVFOVChanged ( wxCommandEvent & e )
3000{
3002
3003 wxString text = m_VFOVText->GetValue();
3004 DEBUG_INFO ("VFOV = " << text.mb_str(wxConvLocal) );
3005 if (text == wxEmptyString) {
3006 return;
3007 }
3008
3009 double vfov;
3011 wxLogError(_("Value must be numeric."));
3012 return;
3013 }
3014
3015 if ( vfov <=0 || vfov > opt.getMaxVFOV()) {
3016 wxLogError(wxString::Format(
3017 _("Invalid VFOV value. Maximum VFOV for this projection is %lf."),
3018 opt.getMaxVFOV()));
3019 vfov = opt.getMaxVFOV();
3020 }
3021 opt.setVFOV(vfov);
3022 // recalculate panorama height...
3025 );
3026
3027 DEBUG_INFO ( "new vfov: " << vfov )
3028};
3029
3031{
3032 if(m_mode==mode_layout)
3033 {
3034 double scale_factor=XRCCTRL(*this,"layout_scale_slider",wxSlider)->GetValue();
3035 m_GLPreview->SetLayoutScale(10.0 - sqrt(scale_factor));
3036 m_GLOverview->SetLayoutScale(10.0 - sqrt(scale_factor));
3037 m_GLPreview->Refresh();
3038 m_GLOverview->Refresh();
3039 };
3040};
3041
3043{
3045 double hfov = opts.getHFOV();
3046 double vfov = opts.getVFOV();
3047 double maxfov = hfov > vfov ? hfov : vfov;
3049 // If this is set to true, offer rectilinear as an alternative if it fits.
3050 bool rectilinear_option = false;
3051 switch (opts.getProjection()) {
3053 if (maxfov > 120.0) {
3054 // wide rectilinear image
3055 message = _("With a wide field of view, panoramas with rectilinear projection get very stretched towards the edges.\n");
3056 if (vfov < 110) {
3057 message += _("Since the field of view is only very wide in the horizontal direction, try a cylindrical projection instead.");
3058 } else {
3059 message += _("For a very wide panorama, try equirectangular projection instead.");
3060 }
3061 message += " ";
3062 message += _("You could also try Panini projection.");
3063 }
3064 break;
3066 if (vfov > 120.0) {
3067 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.");
3068 } else rectilinear_option = true;
3069 break;
3071 if (vfov < 110.0 && hfov > 120.0)
3072 {
3073 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.");
3074 } else rectilinear_option = true;
3075 break;
3077 if (maxfov < 280.0) {
3078 rectilinear_option = true;
3079 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.");
3080 }
3081 break;
3083 if (maxfov > 300.0) {
3084 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.");
3085 } else rectilinear_option = true;
3086 break;
3087 default:
3088 rectilinear_option = true;
3089 }
3090 if (rectilinear_option && maxfov < 110.0) {
3091 message = _("Setting the panorama to rectilinear projection would keep the straight lines straight.");
3092 }
3093 if (message.IsEmpty()) {
3094 // no message needed.
3095 m_infoBar->Dismiss();
3096 } else {
3097 m_infoBar->ShowMessage(message, wxICON_INFORMATION);
3098 }
3099};
3100
3102{
3105 {
3106 m_infoBar->Dismiss();
3107 };
3108};
3109
3111{
3112 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."),
3113 _("Hugin"), wxOK | wxICON_INFORMATION, this);
3114 wxConfigBase* cfg=wxConfigBase::Get();
3115 cfg->Write("/GLPreviewFrame/ShowProjectionHints", false);
3117 cfg->Flush();
3118 e.Skip();
3119};
3120
3136
3148
3152
3153void GLPreviewFrame::OnGuideChanged(wxCommandEvent &e)
3154{
3156 {
3157 int selection=e.GetSelection();
3159 //synchronize wxChoice in projection and crop tab
3160 m_GuideChoiceCrop->SetSelection(selection);
3161 m_GuideChoiceProj->SetSelection(selection);
3162 m_GuideChoiceDrag->SetSelection(selection);
3163 redrawPreview();
3164 };
3165};
3166
3168{
3169 int old_selection=m_DragModeChoice->GetSelection();
3171 {
3172 old_selection=0;
3173 };
3174 m_DragModeChoice->Clear();
3175 m_DragModeChoice->Append(_("normal"));
3176 m_DragModeChoice->Append(_("normal, individual"));
3177 if(newLevel==GUI_EXPERT)
3178 {
3179 m_DragModeChoice->Append(_("mosaic"));
3180 m_DragModeChoice->Append(_("mosaic, individual"));
3181 m_DragModeChoice->SetSelection(old_selection);
3182 }
3183 else
3184 {
3185 if(old_selection>1)
3186 {
3187 m_DragModeChoice->SetSelection(old_selection-2);
3188 }
3189 else
3190 {
3191 m_DragModeChoice->SetSelection(old_selection);
3192 };
3193 };
3194 DragChoiceLayout(m_DragModeChoice->GetSelection());
3195 wxCommandEvent dummy;
3197
3198 old_selection=m_OverviewModeChoice->GetSelection();
3199 m_OverviewModeChoice->Clear();
3200 m_OverviewModeChoice->Append(_("Panosphere (outside)"));
3201 m_OverviewModeChoice->Append(_("Panosphere (inside)"));
3202 if(newLevel==GUI_EXPERT)
3203 {
3204 m_OverviewModeChoice->Append(_("Mosaic plane"));
3205 };
3207 {
3208 m_OverviewModeChoice->SetSelection(2);
3209 }
3210 else
3211 {
3213 m_OverviewModeChoice->SetSelection(0);
3214 };
3215 if(newLevel==GUI_SIMPLE)
3216 {
3217#ifdef __WXMAC__
3218 wxApp::s_macExitMenuItemId = XRCID("action_exit_preview");
3219#endif
3221 {
3222 GetMenuBar()->Remove(0);
3223 GetMenuBar()->Insert(0, m_filemenuSimple, _("&File"));
3224 };
3226 }
3227 else
3228 {
3229#ifdef __WXMAC__
3230 wxApp::s_macExitMenuItemId = XRCID("action_exit_hugin");
3231#endif
3233 {
3234 GetMenuBar()->Remove(0);
3235 GetMenuBar()->Insert(0, m_filemenuAdvanced, _("&File"));
3236 };
3237 SetTitle(_("Fast Panorama preview"));
3238 };
3240 // update menu items
3241 switch(m_guiLevel)
3242 {
3243 case GUI_SIMPLE:
3244 GetMenuBar()->FindItem(XRCID("action_gui_simple"))->Check();
3245 break;
3246 case GUI_ADVANCED:
3247 GetMenuBar()->FindItem(XRCID("action_gui_advanced"))->Check();
3248 break;
3249 case GUI_EXPERT:
3250 GetMenuBar()->FindItem(XRCID("action_gui_expert"))->Check();
3251 break;
3252 };
3253};
3254
3256{
3257 if (id == -1)
3258 {
3259 m_createButton->GetSplitButtonMenu()->AppendSeparator();
3260 }
3261 else
3262 {
3263 m_createButton->GetSplitButtonMenu()->Append(id, desc, help);
3264 };
3265};
3266
3268{
3269 if (id == -1)
3270 {
3271 m_alignButton->GetSplitButtonMenu()->AppendSeparator();
3272 }
3273 else
3274 {
3275 m_alignButton->GetSplitButtonMenu()->Append(id, desc, help);
3276 };
3277};
3278
3279void GLPreviewFrame::OnShowMainFrame(wxCommandEvent &e)
3280{
3281 MainFrame::Get()->Show();
3282 MainFrame::Get()->Raise();
3283};
3284
3285void GLPreviewFrame::OnUserExit(wxCommandEvent &e)
3286{
3287 Close();
3288};
3289
3291{
3292 if (wxConfig::Get()->Read("/ShowFisheyeCropHint", 1l) == 1)
3293 {
3294 // show hint about crop and open tab when requested
3295 wxDialog dlg;
3296 wxXmlResource::Get()->LoadDialog(&dlg, NULL, "fisheye_show_crop_dlg");
3297 if (dlg.ShowModal() == wxID_OK)
3298 {
3299 MainFrame::Get()->ShowMaskEditor(0, true);
3300 };
3301 if (XRCCTRL(dlg, "fisheye_crop_dont_ask_checkbox", wxCheckBox)->IsChecked())
3302 {
3303 wxConfig::Get()->Write("/ShowFisheyeCropHint", 0l);
3304 };
3305 };
3306}
3307
3308void GLPreviewFrame::OnLoadImages(wxCommandEvent& e)
3309{
3310 // load all images with default lens type
3311 LoadImages(-1);
3312}
3313
3315{
3316 // load the images.
3318 HuginBase::UIntSet images;
3320 if(cmd==NULL)
3321 {
3322 return;
3323 }
3324 //distribute images only if the existing images are not connected
3325 //otherwise it would destruct the existing image pattern
3327
3328 const long autoAlign = wxConfigBase::Get()->Read("/Assistant/autoAlign", HUGIN_ASS_AUTO_ALIGN);
3329 if (autoAlign)
3330 {
3332 wxCommandEvent dummy;
3333 OnAlign(dummy);
3334 }
3335 else
3336 {
3337 std::vector<PanoCommand::PanoCommand*> cmds;
3338 cmds.push_back(cmd);
3340 {
3342 cmds.push_back(new PanoCommand::CenterPanoCmd(m_pano));
3343 };
3345 combinedCmd->setName("add and distribute images");
3348 {
3349 // show hint about crop for fisheye images
3350 // skip display if we read the information from our lens database
3351 HuginBase::FileMetaData metaData=m_pano.getImage(0).getFileMetadata();
3352 HuginBase::FileMetaData::const_iterator pos = metaData.find("readProjectionFromDB");
3353 if(!(pos != metaData.end() && pos->second == "true"))
3354 {
3356 };
3357 };
3358 };
3359}
3360
3361void GLPreviewFrame::OnAlign( wxCommandEvent & e )
3362{
3363 // run default assisant
3365}
3366
3367void GLPreviewFrame::OnCreate( wxCommandEvent & e )
3368{
3370 if(dlg.ShowModal()==wxID_OK)
3371 {
3373 new PanoCommand::SetPanoOptionsCmd(m_pano, dlg.GetNewPanoramaOptions())
3374 );
3375 wxCommandEvent dummy;
3377 };
3378}
3379
3380// remove cp, relatively easy, we get the selected cp from the edit cp tool
3381void GLPreviewFrame::OnRemoveCP(wxCommandEvent & e)
3382{
3385 // ask user, if pano should be optimized
3386 long afterEditCPAction = wxConfig::Get()->Read("/EditCPAfterAction", 0l);
3387 bool optimize = false;
3388 if (afterEditCPAction == 0)
3389 {
3390 wxDialog dlg;
3391 wxXmlResource::Get()->LoadDialog(&dlg, this, "edit_cp_optimize_dialog");
3392 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())));
3393 XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3394 dlg.Fit();
3395 optimize = (dlg.ShowModal() == wxID_OK);
3396 if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3397 {
3398 if (optimize)
3399 {
3400 wxConfig::Get()->Write("/EditCPAfterAction", 1l);
3401 }
3402 else
3403 {
3404 wxConfig::Get()->Write("/EditCPAfterAction", 2l);
3405 };
3406 };
3407 }
3408 else
3409 {
3410 optimize = (afterEditCPAction == 1);
3411 }
3412 if (optimize)
3413 {
3414 // invoke optimization routine
3415 wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3416 MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3417 };
3418};
3419
3420// some helper for cp generation
3421// maximal width for remapping for cp generating
3422#define MAX_DIMENSION 1600
3424{
3425 size_t imgNr;
3426 vigra::BRGBImage image;
3427 vigra::BImage mask;
3428};
3429
3430typedef std::vector<FindStruct> FindVector;
3431typedef std::multimap<double, vigra::Diff2D> MapPoints;
3432
3434
3435void GLPreviewFrame::OnCreateCP(wxCommandEvent & e)
3436{
3438 vigra::Rect2D roi = edit_cp_tool->GetSelectedROI();
3440 // some checking of conditions
3441 if (imgs.empty())
3442 {
3443 hugin_utils::HuginMessageBox(_("The selected region contains no active image.\nPlease select a region which is covered by at least 2 images."),
3444 _("Hugin"), wxOK | wxICON_INFORMATION, this);
3445 return;
3446 };
3447 if (imgs.size() < 2)
3448 {
3449 hugin_utils::HuginMessageBox(_("The selected region is only covered by a single image.\nCan't create control points for a single image."),
3450 _("Hugin"), wxOK | wxICON_INFORMATION, this);
3451 return;
3452 };
3453 if (roi.width() > 0.25 * m_pano.getOptions().getWidth())
3454 {
3455 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?"),
3456 _("Hugin"), wxYES_NO | wxICON_INFORMATION, this) == wxNO)
3457 {
3458 return;
3459 };
3460 }
3462 opts.setROI(roi);
3463 // don't correct exposure
3464 opts.outputExposureValue = 0;
3465 // don't use GPU for remapping, this interfere with the fast preview window
3466 opts.remapUsingGPU = false;
3467 // rescale if size is too big
3468 if (roi.width() > MAX_DIMENSION)
3469 {
3470 opts.setWidth(opts.getWidth() * MAX_DIMENSION / roi.width(), true);
3471 roi = opts.getROI();
3472 };
3474 {
3475 ProgressReporterDialog progress(2*imgs.size()+1, _("Searching control points"), _("Processing"), this);
3476 // remap all images to panorama projection
3479 for (HuginBase::UIntSet::const_iterator it = imgs.begin(); it != imgs.end(); ++it)
3480 {
3481 const size_t imgNr = *it;
3482 if (!progress.updateDisplayValue(_("Remap image to panorama projection...")))
3483 {
3484 return;
3485 };
3487 findStruct.imgNr = imgNr;
3488 // remap image to panorama projection
3489 ImageCache::ImageCacheRGB8Ptr CachedImg = ImageCache::getInstance().getImage(m_pano.getImage(imgNr).getFilename())->get8BitImage();
3490
3493 // don't correct exposure
3494 srcImg.setExposureValue(0);
3495 remapped->setPanoImage(srcImg, opts, roi);
3496 remapped->remapImage(vigra::srcImageRange(*CachedImg), vigra_ext::INTERP_CUBIC, &progress);
3497 if (!progress.updateDisplay())
3498 {
3499 delete remapped;
3500 return;
3501 };
3502 findStruct.image = remapped->m_image;
3503 findStruct.mask = remapped->m_mask;
3504 delete remapped;
3505 cpInfos.push_back(findStruct);
3506 };
3507 if (cpInfos.size() > 1)
3508 {
3509 // match keypoints in all image pairs
3510 // select a sensible grid size depending on ratio of selected region, maximal should it be 25 regions
3511 unsigned gridx = hugin_utils::roundi(sqrt((double)roi.width() / (double)roi.height() * 25));
3512 if (gridx < 1)
3513 {
3514 gridx = 1;
3515 }
3516 unsigned gridy = hugin_utils::roundi(25 / gridx);
3517 if (gridy < 1)
3518 {
3519 gridy = 1;
3520 }
3521 while (roi.width() / gridx < 20 && gridx > 1)
3522 {
3523 --gridx;
3524 };
3525 while (roi.height() / gridy < 20 && gridy > 1)
3526 {
3527 --gridy;
3528 };
3529 // template width
3530 const long templWidth = 20;
3531 // search width
3532 const long sWidth = 100;
3533 // match all images with all
3534 for (size_t img1 = 0; img1 < cpInfos.size() - 1; ++img1)
3535 {
3536 if (!progress.updateDisplayValue(_("Matching interest points...")))
3537 {
3538 return;
3539 };
3540 vigra::Size2D size(cpInfos[img1].image.width(), cpInfos[img1].image.height());
3541 // create a number of sub-regions
3542 std::vector<vigra::Rect2D> rects;
3543 for (unsigned party = 0; party < gridy; party++)
3544 {
3545 for (unsigned partx = 0; partx < gridx; partx++)
3546 {
3547 vigra::Rect2D rect(partx*size.x / gridx, party*size.y / gridy,
3548 (partx + 1)*size.x / gridx, (party + 1)*size.y / gridy);
3549 rect &= vigra::Rect2D(size);
3550 if (rect.width()>0 && rect.height()>0)
3551 {
3552 rects.push_back(rect);
3553 };
3554 };
3555 };
3556
3557 if (!progress.updateDisplay())
3558 {
3559 return;
3560 };
3561
3562#pragma omp parallel for schedule(dynamic)
3563 for (int i = 0; i < rects.size(); ++i)
3564 {
3566 vigra::Rect2D rect(rects[i]);
3567 // run interest point detection in sub-region
3568 vigra_ext::findInterestPointsPartial(srcImageRange(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >()), rect, 2, 5 * 8, points);
3569 //check if all points are inside the given image
3571 for (MapPoints::const_iterator it = points.begin(); it != points.end(); ++it)
3572 {
3573 if (cpInfos[img1].mask(it->second.x, it->second.y)>0)
3574 {
3575 validPoints.insert(*it);
3576 };
3577 };
3578
3579 if (!validPoints.empty())
3580 {
3581 // now fine-tune the interest points with all other images
3582 for (size_t img2 = img1 + 1; img2 < cpInfos.size(); ++img2)
3583 {
3584 unsigned nGood = 0;
3585 // loop over all points, starting with the highest corner score
3586 for (MapPoints::const_reverse_iterator it = validPoints.rbegin(); it != validPoints.rend(); ++it)
3587 {
3588 if (nGood >= 2)
3589 {
3590 // we have enough points, stop
3591 break;
3592 }
3593 //check if point is covered by second image
3594 if (cpInfos[img2].mask(it->second.x, it->second.y) == 0)
3595 {
3596 continue;
3597 };
3598 // finally fine-tune point
3599 vigra_ext::CorrelationResult res = vigra_ext::PointFineTune(cpInfos[img1].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, templWidth,
3600 cpInfos[img2].image, vigra::RGBToGrayAccessor<vigra::RGBValue<vigra::UInt8> >(), it->second, sWidth);
3601 if (res.maxi < 0.9)
3602 {
3603 continue;
3604 }
3605 nGood++;
3606 // add control point
3607 {
3609 tempCps.push_back(HuginBase::ControlPoint(cpInfos[img1].imgNr, it->second.x, it->second.y,
3610 cpInfos[img2].imgNr, res.maxpos.x, res.maxpos.y, HuginBase::ControlPoint::X_Y));
3611 };
3612 };
3613 };
3614 };
3615 };
3616 // free memory
3617 cpInfos[img1].image.resize(0, 0);
3618 cpInfos[img1].mask.resize(0, 0);
3619 };
3620
3621 // transform coordinates back to image space
3622 for (size_t i = 0; i < tempCps.size(); ++i)
3623 {
3625 hugin_utils::FDiff2D p1(cp.x1 + roi.left(), cp.y1 + roi.top());
3628 transform.createTransform(m_pano.getImage(cp.image1Nr), opts);
3629 if (transform.transformImgCoord(p1Img, p1))
3630 {
3631 hugin_utils::FDiff2D p2(cp.x2 + roi.left(), cp.y2 + roi.top());
3633 transform.createTransform(m_pano.getImage(cp.image2Nr), opts);
3634 if (transform.transformImgCoord(p2Img, p2))
3635 {
3636 cp.x1 = p1Img.x;
3637 cp.y1 = p1Img.y;
3638 cp.x2 = p2Img.x;
3639 cp.y2 = p2Img.y;
3640 cps.push_back(cp);
3641 };
3642 };
3643 };
3644
3645 if (!cps.empty())
3646 {
3647 // check newly found control points
3648 // create copy
3650 // remove all cps and set only the new found cp
3652 // now create a subpano with only the selected images
3654 // clean control points
3655 if (!progress.updateDisplayValue(_("Checking results...")))
3656 {
3657 return;
3658 };
3662 if (!invalidCP.empty())
3663 {
3664 for (HuginBase::UIntSet::const_reverse_iterator it = invalidCP.rbegin(); it != invalidCP.rend(); ++it)
3665 {
3666 cps.erase(cps.begin() + *it);
3667 };
3668 }
3669 // force closing progress dialog
3670 if (!progress.updateDisplayValue())
3671 {
3672 return;
3673 };
3675 // ask user, if pano should be optimized
3676 long afterEditCPAction = wxConfig::Get()->Read("/EditCPAfterAction", 0l);
3677 bool optimize = false;
3678 if (afterEditCPAction == 0)
3679 {
3680 // close progress window, otherwise the dialog don't autoamtically get the focus
3681 wxYield();
3682 wxDialog dlg;
3683 wxXmlResource::Get()->LoadDialog(&dlg, this, "edit_cp_optimize_dialog");
3684 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())));
3685 XRCCTRL(dlg, "edit_cp_text2", wxStaticText)->SetLabel(wxString::Format(_("Current selected optimizer strategy is \"%s\"."), MainFrame::Get()->GetCurrentOptimizerString().c_str()));
3686 dlg.Fit();
3687 optimize = (dlg.ShowModal() == wxID_OK);
3688 if (XRCCTRL(dlg, "edit_cp_dont_show_again_checkbox", wxCheckBox)->GetValue())
3689 {
3690 if (optimize)
3691 {
3692 wxConfig::Get()->Write("/EditCPAfterAction", 1l);
3693 }
3694 else
3695 {
3696 wxConfig::Get()->Write("/EditCPAfterAction", 2l);
3697 };
3698 };
3699 }
3700 else
3701 {
3702 optimize = (afterEditCPAction == 1);
3703 }
3704 if (optimize)
3705 {
3706 // invoke optimization routine
3707 wxCommandEvent ev(wxEVT_COMMAND_BUTTON_CLICKED, XRCID("action_optimize"));
3708 MainFrame::Get()->GetEventHandler()->AddPendingEvent(ev);
3709 };
3710 };
3711 };
3712 };
3713 // finally redraw
3714 m_GLPreview->Update();
3715 m_GLPreview->Refresh();
3716};
3717
3718void GLPreviewFrame::OnSelectAllMenu(wxCommandEvent& e)
3719{
3720 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 0l);
3722};
3723
3725{
3726 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 1l);
3728};
3729
3731{
3732 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 2l);
3734};
3735
3737{
3738 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllMode", 3l);
3740};
3741
3743{
3744 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllKeepSelection", true);
3745 m_selectKeepSelection = true;
3746};
3747
3749{
3750 wxConfig::Get()->Write("/GLPreviewFrame/SelectAllKeepSelection", false);
3751 m_selectKeepSelection = false;
3752}
3753
3755{
3756 // store image number
3757 m_imageMenuIndex = e.GetId() - ID_TOGGLE_BUT;
3758 m_imageMenu.FindItem(m_removeImageMenuId)->SetItemLabel(wxString::Format(_("Remove image %s"), m_ToggleButtons[m_imageMenuIndex]->GetToolTipText()));
3759 // show popup menu
3761}
3762
3763void GLPreviewFrame::OnRemoveImage(wxCommandEvent& e)
3764{
3765 // remove image as selected with context menu
3766 if (m_imageMenuIndex != -1)
3767 {
3769 m_imageMenuIndex = -1;
3770 }
3771}
algorithms for remove control points by statistic method
@ mode_drag
@ mode_preview
@ mode_assistant
@ mode_projection
@ mode_layout
@ mode_crop
#define PF_STYLE
std::vector< FindStruct > FindVector
@ PROJ_PARAM_NAMES_ID
@ ID_SHOW_ALL
@ ID_SHOW_NONE
@ ID_HIDE_HINTS
@ ID_TOGGLE_BUT
@ ID_CREATEPANO_MENU
@ ID_ASS_LOAD_IMAGES
@ ID_TOGGLE_BUT_LEAVE
@ PROJ_PARAM_SLIDER_ID
@ ID_ASSISTANT_MENU
@ PROJ_PARAM_RESET_ID
@ PROJ_PARAM_VAL_ID
@ ID_FULL_SCREEN
#define MAX_DIMENSION
std::multimap< double, vigra::Diff2D > MapPoints
static hugin_omp::Lock cpLock
void ShowFisheyeCropHint()
GuiLevel
Definition GuiLevel.h:32
@ GUI_EXPERT
Definition GuiLevel.h:35
@ GUI_ADVANCED
Definition GuiLevel.h:34
@ GUI_SIMPLE
Definition GuiLevel.h:33
compute interest points
declaration of functions to handle stacks and layers
WXIMPEX HuginLensTools::LensInfoVector GetLensProjectionList()
return a vector with all available projections
Definition LensTools.cpp:46
some helper classes for graphes
void registerPTWXDlgFcn()
Definition PTWXDlg.cpp:178
void deregisterPTWXDlgFcn()
Definition PTWXDlg.cpp:185
Definition of PanoOperation class.
Definition of PanoOutputDialog class.
interface of ToolHelper for deleting control points in the pano space
@ ID_CREATE_CP
@ ID_REMOVE_CP
interface to ToolHelper for drawing guide lines over pano
implementation of PanosphereSphereTool Class
Definition of dialog for selecting and editing aspect ratios of crop.
Allows the user to change the yaw, pitch and roll of a connected component of images by dragging them...
Definition DragTool.h:51
@ drag_mode_normal
Definition DragTool.h:72
@ drag_mode_mosaic
Definition DragTool.h:73
void setDragMode(DragMode drag_mode)
Definition DragTool.cpp:47
DragMode getDragMode()
Definition DragTool.cpp:52
OverviewMode GetMode()
Definition GLViewer.h:151
void SetMode(OverviewMode mode)
Definition GLViewer.cpp:492
virtual void SetLayoutScale(double scale)
Definition GLViewer.cpp:314
@ PANOSPHERE_OUTSIDE
Definition GLViewer.h:145
@ PANOSPHERE_INSIDE
Definition GLViewer.h:146
virtual void SetLayoutMode(bool state)
Definition GLViewer.cpp:307
The OpenGL preview frame.
void OnResetCrop(wxCommandEvent &e)
event handler to reset crop area
void OnImageContextMenu(wxContextMenuEvent &e)
show context menu on image buttons
void LoadImages(int preferredLensType)
void OnAutocrop(wxCommandEvent &e)
void EnableGroupCheckboxes(bool isShown)
changes the visibility of the group check boxes
PreviewProjectionGridTool * preview_projection_grid
PreviewControlPointTool * panosphere_control_point_tool
void OnProjectionChoice(wxCommandEvent &e)
PanosphereOverviewCameraTool * panosphere_overview_camera_tool
virtual void panoramaChanged(HuginBase::Panorama &pano)
Notification about a Panorama change.
void OnStraighten(wxCommandEvent &e)
void ResetTranslationPlaneParameters()
resets all translation plane parameters to zero
void OnCenterHorizontally(wxCommandEvent &e)
wxChoice * m_OverviewModeChoice
void KeyDown(wxKeyEvent &e)
void OnFitPano(wxCommandEvent &e)
wxBoxSizer * m_topsizer
void OnSelectResetSelection(wxCommandEvent &e)
PreviewControlPointTool * preview_control_point_tool
void OnClose(wxCloseEvent &e)
void OnCreateCP(wxCommandEvent &e)
handler for creating cp in pano space
wxMenu * m_filemenuSimple
void InitPreviews()
init previews
void OnBlendChoice(wxCommandEvent &e)
PreviewPanoMaskTool * pano_mask_tool
void OnRangeCompressionIncrease(wxSpinEvent &e)
void OnIncreaseExposure(wxSpinEvent &e)
void OnTrackChangeProjectionParam(wxScrollEvent &e)
void DragChoiceLayout(int index)
PreviewControlPointTool * plane_control_point_tool
void OnSetCropAspect(wxCommandEvent &e)
event handler to set fixed aspect ratio of crop
std::vector< ImageGroupButtonEventHandler * > toggle_group_button_event_handlers
PreviewDragTool * drag_tool
PreviewIdentifyTool * panosphere_overview_identify_tool
void OnSelectAllMenu(wxCommandEvent &e)
handle all options of select all context menu
void OnSelectDarkestMenu(wxCommandEvent &e)
wxColour m_preview_background_color
void OnStackAutocrop(wxCommandEvent &e)
wxToggleButton * m_identify_togglebutton
void TurnOffTools(std::set< Tool * > tools)
PlaneOverviewToolHelper * plane_overview_helper
PlaneOverviewOutlinesTool * plane_overview_outlines_tool
void OnSwitchPreviewGrid(wxCommandEvent &e)
event handler for switch on/off grid on preview
PreviewLayoutLinesTool * m_preview_layoutLinesTool
wxSlider * m_VFOVSlider
void UpdateRoiDisplay(const HuginBase::PanoramaOptions opts)
update display of ROI
void OnOverviewModeChoice(wxCommandEvent &e)
void OnEditCPTool(wxCommandEvent &e)
event handler when starting edit cp tool
wxToggleButton * m_colorpicker_togglebutton
void updateBlendMode()
Update tools and GUI elements according to blend mode choice.
virtual ~GLPreviewFrame()
dtor.
void OnDefaultExposure(wxCommandEvent &e)
void OnShowNone(wxCommandEvent &e)
void OnCreate(wxCommandEvent &e)
void MakePlaneOverviewTools(PlaneOverviewToolHelper *helper)
void OnShowEvent(wxShowEvent &e)
HuginBase::UIntSet GetDragGroupImages()
wxInfoBar * m_infoBar
Bar for context sensitive projection information.
wxChoice * m_GuideChoiceCrop
wxTextCtrl * m_ROILeftTxt
wxTextCtrl * m_ROIRightTxt
void ClearDragGroupImages(bool update_check_box=true)
void FillBlendChoice()
fills the blend wxChoice with all valid blend modes and restore the last used one
void SetGuiLevel(GuiLevel newLevel)
sets the gui level
PreviewIdentifyTool * identify_tool
void OnOverviewToggle(wxCommandEvent &e)
wxSpinButton * m_exposureSpinBut
PreviewDifferenceTool * panosphere_difference_tool
HuginBase::Panorama & m_pano
wxNotebook * m_tool_notebook
wxChoice * m_GuideChoiceProj
PlaneOverviewCameraTool * plane_overview_camera_tool
void SetMode(int newMode)
PanosphereOverviewProjectionGridTool * overview_projection_grid
void OnExposureChanged(wxCommandEvent &e)
void MakePreviewTools(PreviewToolHelper *helper)
void ToggleImageInDragGroup(unsigned int image_nr, bool update_check_box=true)
wxPanel * m_overviewCommandPanel
PanosphereOverviewToolHelper * panosphere_overview_helper
PreviewToolHelper * preview_helper
void OnROIChanged(wxCommandEvent &e)
event handler for changed roi
void SetStatusMessage(wxString message)
wxBoxSizer * m_projParamSizer
HuginBase::UIntSet imageDragGroup
wxChoice * m_GuideChoiceDrag
wxColour GetPreviewBackgroundColor()
wxPanel * m_projection_panel
bool HasNonZeroTranslationPlaneParameters()
check, if panorama has non-zero translation plane parameters
void LoadOpenGLLayout()
loads the layout of the OpenGL windows and restores it
wxToggleButton * m_editCP_togglebutton
wxTextCtrl * m_ROITopTxt
void OnLoadImages(wxCommandEvent &e)
bool UpdateOverviewMode(int newMode)
updates the mode of the overview window
void OnDragChoice(wxCommandEvent &e)
wxMenu * m_filemenuAdvanced
SelectAllMode m_selectAllMode
void StorePositionAndSize()
store position and size of window in wxConfig
wxStaticBoxSizer * m_ToggleButtonSizer
PreviewColorPickerTool * color_picker_tool
std::vector< wxCheckBox * > m_GroupToggleButtons
wxChoice * m_DragModeChoice
PreviewIdentifyTool * plane_overview_identify_tool
void AddUserDefinedSequence(int id, const wxString &desc, const wxString &help)
adds the given user defined output sequence to SplitButton menu
void RemoveImageFromDragGroup(unsigned int image_nr, bool update_check_box=true)
void OnControlPoint(wxCommandEvent &e)
void OnProjParameterChanged(wxCommandEvent &e)
void redrawPreview()
Display an updated version of the preview images.
wxChoice * m_BlendModeChoice
void OnUserExit(wxCommandEvent &e)
user wants to quit program
void OnDecreaseExposure(wxSpinEvent &e)
void OnShowAll(wxCommandEvent &e)
void AddUserDefinedAssistant(int id, const wxString &desc, const wxString &help)
adds the given user defined assistant to SplitButton menu
void OnAutocropOutside(wxCommandEvent &e)
void UpdateIdentifyTools(std::set< unsigned int > new_image_set)
PreviewDifferenceTool * plane_difference_tool
void SetDragGroupImages(HuginBase::UIntSet imageDragGroup_in, bool update_check_box=true)
void OnFullScreen(wxCommandEvent &e)
event handler for full screen
void OnSelectKeepSelection(wxCommandEvent &e)
void OnPreviewBackgroundColorChanged(wxColourPickerEvent &e)
event handler when user changes background color
virtual void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &changed)
notifies about changes to images
void OnHideProjectionHints(wxCommandEvent &e)
event handler when user hides the infobar
wxScrolledWindow * m_ButtonPanel
std::vector< wxSlider * > m_projParamSlider
wxTextCtrl * m_HFOVText
void OnSelectBrightestMenu(wxCommandEvent &e)
void OnShowMainFrame(wxCommandEvent &e)
event handler to show main frame
void OnChangeProjectionParam(wxScrollEvent &e)
void AddImageToDragGroup(unsigned int image_nr, bool update_check_box=true)
void OnRangeCompressionChanged(wxCommandEvent &e)
PanosphereOverviewOutlinesTool * overview_outlines_tool
std::vector< wxPanel * > m_ToggleButtonPanel
SplitButton * m_createButton
GLOverview * m_GLOverview
std::vector< ImageToogleButtonEventHandler * > toogle_button_event_handlers
void OnIdentify(wxCommandEvent &e)
void OnRemoveImage(wxCommandEvent &e)
void OnRemoveCP(wxCommandEvent &e)
handler to remove cp
wxChoice * m_ProjectionChoice
PreviewDifferenceTool * difference_tool
PreviewCameraTool * camera_tool
wxTextCtrl * m_rangeCompressionTextCtrl
void OnColorPicker(wxCommandEvent &e)
event handler when starting color picker
wxSlider * m_HFOVSlider
GLwxAuiManager * m_mgr
The dock manager.
void OnVFOVChanged(wxCommandEvent &e)
SplitButton * m_selectAllButton
PreviewCropTool * crop_tool
void ResetPreviewZoom()
reset zoom level for preview window
void OnLayoutScaleChange(wxCommandEvent &e)
event handler for change scale of layout mode
std::vector< wxTextCtrl * > m_projParamTextCtrl
void OnNumTransform(wxCommandEvent &e)
void MakePanosphereOverviewTools(PanosphereOverviewToolHelper *helper)
wxSpinButton * m_rangeCompressionSpinBut
void OnPhotometric(wxCommandEvent &e)
OverviewDragTool * overview_drag_tool
void ShowProjectionWarnings()
Tell the user anything suspicious about the projection choice.
GLPreview * m_GLPreview
void UpdateGlobalWhiteBalance(double redFactor, double blueFactor)
updates the global white balance
SplitButton * m_loadImagesButton
wxTextCtrl * m_VFOVText
PreviewEditCPTool * edit_cp_tool
void OnProjParameterReset(wxCommandEvent &e)
event handler for reset projection parameters
void OnGuideChanged(wxCommandEvent &e)
event handler when user selects different guide
SplitButton * m_alignButton
std::vector< wxStaticText * > m_projParamNamesLabel
wxTextCtrl * m_exposureTextCtrl
void OnSelectMode(wxNotebookEvent &e)
event handler for selection of new mode
wxBoxSizer * m_ButtonSizer
PreviewLayoutLinesTool * m_plane_layoutLinesTool
void OnToolModeChanging(wxNotebookEvent &e)
event handler for blocking changing mode when panorama contains no images
PreviewLayoutLinesTool * m_panosphere_layoutLinesTool
void KeyUp(wxKeyEvent &e)
void SetImageButtonColour(unsigned int image_nr, unsigned char red, unsigned char green, unsigned char blue)
void OnSelectMedianMenu(wxCommandEvent &e)
std::vector< wxToggleButton * > m_ToggleButtons
GLPreviewFrame(wxFrame *frame, HuginBase::Panorama &pano)
ctor.
void SetShowProjectionHints(bool new_value)
set status if projection hints should be shown or not
wxTextCtrl * m_ROIBottomTxt
void OnHFOVChanged(wxCommandEvent &e)
PreviewGuideTool * preview_guide_tool
wxBitmapButton * m_defaultExposureBut
PanosphereSphereTool * panosphere_sphere_tool
void OnRangeCompressionDecrease(wxSpinEvent &e)
void OnAlign(wxCommandEvent &e)
virtual void SetLayoutMode(bool state)
Definition GLViewer.cpp:295
void SetActive(bool active)
Definition GLViewer.h:75
wxGLContext * GetContext()
Definition GLViewer.h:78
VisualizationState * m_visualization_state
Definition GLViewer.h:71
virtual void SetLayoutScale(double scale)
Definition GLViewer.cpp:301
void SetPhotometricCorrect(bool state)
Definition GLViewer.cpp:289
void SetUpContext()
Definition GLViewer.cpp:122
void SetViewerBackground(wxColour col)
Definition GLViewer.cpp:485
void Redraw()
Definition GLViewer.cpp:385
void Resized(wxSizeEvent &e)
Definition GLViewer.cpp:356
static ViewState * m_view_state
Definition GLViewer.h:72
subclass for a floating frame of the dock manager
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 OnActivate(wxActivateEvent &evt)
customized subclass of the dock manager, created just for the purpose to create a workaround for the ...
GLPreviewFrame * frame
GLwxAuiFloatingFrame * CreateFloatingFrame(wxWindow *parent, const wxAuiPaneInfo &p)
virtual double getResultHorizontalFOV()
Definition FitPanorama.h:68
virtual double getResultHeight()
Definition FitPanorama.h:75
static double calcMeanExposure(const PanoramaData &pano)
represents a control point
struct to hold a image state for stitching
Holds transformations for Image -> Pano and the other way.
bool transformImgCoord(double &x_dest, double &y_dest, double x_src, double y_src) const
like transform, but return image coordinates, not cartesian coordinates
void 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->image transformation
virtual void run()
runs the algorithm.
Panorama image options.
void setHFOV(double h, bool keepView=true)
set the horizontal field of view.
void setProjection(ProjectionFormat f)
set the Projection format and adjust the hfov/vfov if nessecary
bool fovCalcSupported(ProjectionFormat f) const
true, if FOV calcuations are supported for projection f
const std::vector< double > & getProjectionParameters() const
Get the optional projection parameters.
const vigra::Rect2D & getROI() const
void setWidth(unsigned int w, bool keepView=true)
set panorama width keep the HFOV, if keepView=true
void setROI(const vigra::Rect2D &val)
unsigned int getWidth() const
void resetProjectionParameters()
sets the optional parameters to their default values
PanoramaOptions::ProjectionFormat getProjection() const
ProjectionFormat
Projection of final panorama.
void setProjectionParameters(const std::vector< double > &params)
set the optional parameters (they need to be of the correct size)
pano_projection_features m_projFeatures
vigra::Size2D getSize() const
get size of output image
Model for a panorama.
Definition Panorama.h:153
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
Definition Panorama.h:211
const PanoramaOptions & getOptions() const
returns the options for this panorama
Definition Panorama.h:481
void setCtrlPoints(const CPVector &points)
set all control points (Ippei: Is this supposed to be 'add' method?)
Definition Panorama.cpp:449
void addObserver(PanoramaObserver *o)
add a panorama observer.
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
std::size_t getNrOfCtrlPoints() const
number of control points
Definition Panorama.h:306
VariableMapVector getVariables() const
get variables of this panorama
Definition Panorama.cpp:118
const CPVector & getCtrlPoints() const
get all control point of this Panorama
Definition Panorama.h:319
Panorama getSubset(const UIntSet &imgs) const
get a subset of the panorama
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
Panorama duplicate() const
duplicate the panorama
UIntSet getActiveImages() const
get active images
bool needsOptimization()
true if control points or lens variables have been changed after the last optimisation
Definition Panorama.h:614
std::size_t getNrOfImages() const
number of images.
Definition Panorama.h:205
All variables of a source image.
bool isCircularCrop() const
returns true, if projection requires cicular crop
class to work with images graphs created from a HuginBase::Panorama class it creates a graph based on...
Definition ImageGraph.h:45
std::vector< HuginBase::UIntSet > Components
stores the components of the graph
Definition ImageGraph.h:50
void OnChange(wxCommandEvent &e)
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
ImageGroupButtonEventHandler(unsigned int image_number, GLPreviewFrame *frame_in, HuginBase::Panorama *m_pano)
void AddDragTool(DragTool **drag_tool_in)
void OnEnter(wxMouseEvent &e)
HuginBase::Panorama * m_pano
void OnLeave(wxMouseEvent &e)
std::vector< PreviewIdentifyTool ** > identify_tools
std::vector< DragTool ** > drag_tools
ImageToogleButtonEventHandler(unsigned int image_number, wxToggleButton *identify_button_in, HuginBase::Panorama *m_pano)
void OnChange(wxCommandEvent &e)
std::vector< PreviewIdentifyTool ** > identify_tools
HuginBase::Panorama * m_pano
void AddIdentifyTool(PreviewIdentifyTool **identify_tool_in)
wxFileHistory * GetFileHistory()
Definition MainFrame.h:187
static MainFrame * Get()
hack.. kind of a pseudo singleton...
void OnDoStitch(wxCommandEvent &e)
void RunAssistant(wxWindow *mainWin, const wxString &userdefinedAssistant=wxEmptyString)
void ShowMaskEditor(size_t imgNr, bool switchToCropMode=false)
opens the mask/crop editor with the given image selected
@ CLOSE_PROGRAM
Definition MainFrame.h:134
add multiple control points
center panorama horizontically
PanoCommand to combine other PanoCommands.
Definition PanoCommand.h:40
std::string getLastCommandName() const
returns the name of the last command
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
distributes all images above the sphere, for the assistant
static GlobalCmdHist & getInstance()
Base class for all panorama commands.
Definition Command.h:39
remove several control points
remove an image from a panorama
Definition PanoCommand.h:80
Rotate the panorama.
set the panorama options
straighten panorama horizontically
Translate the panorama.
update variables of a group of images
update global white balance
simple class that forward the drop to the mainframe
Definition MainFrame.h:62
PanoOperation to add several user selected images to the panorama.
virtual PanoCommand::PanoCommand * GetCommand(wxWindow *parent, HuginBase::Panorama &pano, HuginBase::UIntSet images, GuiLevel guiLevel)
returns the appropriate PanoCommand::PanoCommand to be inserted into GlobalCmdHistory,...
Dialog for setting output parameters for simple user interface.
tool for the manipulation of the opengl 'camera' properties It handles rotation of the camera positio...
void DeactivateTool(Tool *tool)
tool to draw a whiteish transparent sphere for the panosphere
void SetPreviewBackgroundColor(wxColour c)
sets the sphere background color
tool for manipulation of the opengl 'camera' properties It handles the position of the camera in 3 di...
tool for the manipulation of the opengl 'camera' properties It handles zooming in/out of the main pre...
The PreviewColorPickerTool allows to select a region in the panorama which should be grey.
The PreviewCropTool shows lines between the ends of control points in the fast preview.
Allow the user to change the cropping region by dragging it in the fast preview.
Finds the topmost image underneath the mouse pontier, cancel it's normal drawing, and then subtract i...
static bool CheckOpenGLCanDifference()
check, if graphic card supports the necessary modes for difference tool call this procedure first,...
Tool to delete all cp in a selected rectangle.
HuginBase::UIntSet GetFoundCPs()
return set of found control points
vigra::Rect2D GetSelectedROI()
returns selected ROI
void SetMenuProcessed()
reset popup menu status
HuginBase::Panorama & m_pano
wxChoice * m_ProjectionChoice
Draws guide lines over the panorama in fast preview window.
void SetGuideStyle(const Guides newGuideStyle)
sets the guide style to the given style
Visually connect the image numbers with the image on the preview.
void setConstantOn(bool constant_on_in)
void UpdateWithNewImageSet(std::set< unsigned int > new_image_set)
The PreviewLayoutLinesTool handles the lines connecting images in the layout view of the fast preview...
For projections where the output range is limited, but the approximatly remaped images can extend thi...
void SetLabel(const wxString &label) override
set the label string
wxMenu * LoadMenu(const wxString &name)
loads the drop down menu from the XRC ressource
wxMenu * GetSplitButtonMenu()
returns a pointer to the drop down menu
bool Enable(bool enable=true) override
enable or disable the control
void SetBitmap(const wxBitmapBundle &bitmap)
sets bitmap bundle
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
void KeypressEvent(int keycode, int modifiers, bool pressed)
std::set< Tool * > ActivateTool(Tool *tool)
virtual void DeactivateTool(Tool *tool)
void SetOptions(const HuginBase::PanoramaOptions *new_opts)
void SetZoomLevel(const float new_zoom)
void SetDirtyViewport()
Definition ViewState.h:249
static huginApp * Get()
hack.. kind of a pseudo singleton...
Definition huginApp.cpp:651
#define HUGIN_PREVIEW_BACKGROUND
#define HUGIN_ASS_AUTO_ALIGN
#define HUGIN_SHOW_PROJECTION_HINTS
implementation of huginApp Class
#define HUGIN_CONV_FILENAME
Definition platform.h:40
wxString Components2Str(const HuginGraph::ImageGraph::Components &comp)
Definition huginApp.cpp:84
#define DEBUG_ASSERT(cond)
Definition utils.h:80
#define DEBUG_DEBUG(msg)
Definition utils.h:68
#define DEBUG_TRACE(msg)
Definition utils.h:67
#define DEBUG_WARN(msg)
Definition utils.h:74
#define DEBUG_INFO(msg)
Definition utils.h:69
UIntSet getCPoutsideLimit(Panorama pano, double n, bool skipOptimisation, bool includeLineCp)
optimises the whole panorama and removes all control points with error > mean+n*sigma
Definition CleanCP.cpp:123
std::vector< ControlPoint > CPVector
std::vector< HuginBase::UIntVector > getSortedStacks(const HuginBase::Panorama *pano)
returns vector of UIntVector with image numbers of each stack sorted by exposure
UIntSet getImagesinROI(const PanoramaData &pano, const UIntSet activeImages)
returns set of images which are visible in output ROI
std::set< unsigned int > UIntSet
std::map< std::string, std::string > FileMetaData
typedef for general map for storing metadata in files
std::vector< LensInfo > LensInfoVector
vector of LensInfo to hold all available lens types
Definition LensTools.h:48
bool str2double(const wxString &s, double &d)
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
Definition wxutils.cpp:176
std::string doubleToString(double d, int digits)
convert a double to a string, suitable for display within a GUI.
Definition utils.cpp:228
int floori(double x)
Definition hugin_math.h:65
int roundi(T x)
Definition hugin_math.h:73
int gcd(int a, int b)
function to calculate greated common divisor using Euclidean algorithm both arguments should be >=0
bool stringToDouble(const STR &str_, double &dest)
convert a string to a double, ignore localisation.
Definition utils.h:114
void StoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:106
void RestoreFramePosition(wxTopLevelWindow *frame, const wxString &basename, const bool ignoreMaximize)
Definition wxutils.cpp:67
void findInterestPointsPartial(vigra::triple< ImageIter, ImageIter, ImageAcc > img, const vigra::Rect2D &rect, double scale, unsigned nPoints, std::multimap< double, vigra::Diff2D > &points)
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
helper for OpenMP
include file for the hugin project
include file for the hugin project
bool set_contains(const _Container &c, const typename _Container::key_type &key)
Definition stl_utils.h:74
void fill_set(_Container &c, typename _Container::key_type begin, typename _Container::key_type end)
Definition stl_utils.h:81
vigra::BRGBImage image
vigra::BImage mask
Maximum of correlation, position and value.
Definition Correlation.h:57
hugin_utils::FDiff2D maxpos
Definition Correlation.h:64
std::vector< deghosting::BImagePtr > threshold(const std::vector< deghosting::FImagePtr > &inputImages, const double threshold, const uint16_t flags)
Threshold function used for creating alpha masks for images.
Definition threshold.h:41
wxwindows specific panorama commands
platform/compiler specific stuff.