39 #include <wx/clipbrd.h>
57 if (! wxPanel::Create(parent,
id, pos, size, style, name))
65 wxXmlResource::Get()->LoadPanel(
this, wxT(
"mask_panel"));
66 wxPanel * panel = XRCCTRL(*
this,
"mask_panel", wxPanel);
68 wxBoxSizer *topsizer =
new wxBoxSizer( wxVERTICAL );
69 topsizer->Add(panel, 1, wxEXPAND, 0);
80 m_imagesListMask->InsertColumn(2, _(
"Number of masks"), wxLIST_FORMAT_RIGHT, 120);
88 wxConfigBase* config = wxConfigBase::Get();
92 int width = config->Read(wxString::Format(
"/ImagesListMask/ColumnWidth%d", j), -1);
99 m_maskList = XRCCTRL(*
this,
"mask_editor_mask_list", wxListCtrl);
100 m_maskList->InsertColumn( 0, wxT(
"#"), wxLIST_FORMAT_RIGHT, 35);
101 m_maskList->InsertColumn( 1, _(
"Mask type"), wxLIST_FORMAT_LEFT, 120);
106 m_maskCropCtrl = XRCCTRL(*
this,
"mask_editor_mask_crop_notebook", wxNotebook);
113 for (
int j=0; j <
m_maskList->GetColumnCount() ; j++ )
116 int width = config->Read(wxString::Format( wxT(
"/MaskEditorPanel/ColumnWidth%d"), j ), -1);
121 config->Read(wxT(
"/MaskEditorPanel/ShowActiveMasks"),&activeMasks,
false);
122 XRCCTRL(*
this,
"mask_editor_show_active_masks",wxCheckBox)->SetValue(activeMasks);
126 wxColour defaultColour;
128 wxColour colour = config->Read(wxT(
"/MaskEditorPanel/ColourPolygonNegative"), defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
129 XRCCTRL(*
this,
"mask_editor_colour_polygon_negative",wxColourPickerCtrl)->SetColour(colour);
132 colour = config->Read(wxT(
"/MaskEditorPanel/ColourPolygonPositive"), defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
133 XRCCTRL(*
this,
"mask_editor_colour_polygon_positive",wxColourPickerCtrl)->SetColour(colour);
136 colour = config->Read(wxT(
"/MaskEditorPanel/ColourPointSelected"), defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
137 XRCCTRL(*
this,
"mask_editor_colour_point_selected",wxColourPickerCtrl)->SetColour(colour);
140 colour = config->Read(wxT(
"/MaskEditorPanel/ColourPointUnselected"), defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
141 XRCCTRL(*
this,
"mask_editor_colour_point_unselected",wxColourPickerCtrl)->SetColour(colour);
146 m_maskType = XRCCTRL(*
this,
"mask_editor_choice_masktype", wxChoice);
152 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->Disable();
153 XRCCTRL(*
this,
"mask_editor_add", wxButton)->Disable();
154 XRCCTRL(*
this,
"mask_editor_load", wxButton)->Disable();
155 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Disable();
156 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Disable();
157 XRCCTRL(*
this,
"mask_editor_paste", wxButton)->Disable();
158 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Disable();
165 m_cropLens = XRCCTRL(*
this,
"crop_all_images_lens", wxCheckBox);
167 bool doCropImagesLens;
168 config->Read(wxT(
"/MaskEditorPanel/CropImagesLens"), &doCropImagesLens,
true);
191 wxAcceleratorEntry entries[2];
192 entries[0].Set(wxACCEL_CMD,(
int)
'C',XRCID(
"mask_editor_copy"));
193 entries[1].Set(wxACCEL_CMD,(
int)
'V',XRCID(
"mask_editor_paste"));
194 wxAcceleratorTable accel(2, entries);
195 SetAcceleratorTable(accel);
198 wxCommandEvent dummy;
199 dummy.SetInt(XRCCTRL(*
this,
"mask_editor_choice_zoom",wxChoice)->GetSelection());
228 wxConfigBase* config = wxConfigBase::Get();
229 config->Write(wxT(
"/MaskEditorPanel/ShowActiveMasks"),XRCCTRL(*
this,
"mask_editor_show_active_masks",wxCheckBox)->GetValue());
231 config->Write(wxT(
"/MaskEditorPanel/CropImagesLens"),
m_cropLens->GetValue());
256 unsigned int nrItems = list->GetItemCount();
258 for (
unsigned int i = 0; i < nrItems; i++)
264 list->SetItemState(i, 0, wxLIST_STATE_SELECTED);
266 list->SetItemState(imgNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
272 bool restoreMaskSelection=(imgNr==
GetImgNr());
273 bool updateImage=
true;
275 if (imgNr == UINT_MAX)
285 updateImage=(
m_File!=image.getFilename());
287 m_File=image.getFilename();
292 m_File=image.getFilename();
295 masksToDraw=image.getActiveMasks();
306 bool enableCtrl=(imgNr<UINT_MAX);
307 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
308 XRCCTRL(*
this,
"mask_editor_add", wxButton)->Enable(enableCtrl);
309 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
310 XRCCTRL(*
this,
"mask_editor_load", wxButton)->Enable(enableCtrl);
311 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
312 XRCCTRL(*
this,
"mask_editor_paste", wxButton)->Enable(enableCtrl);
313 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
316 ImageCache::getInstance().softFlush();
317 if(updateListSelection)
329 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(
m_MaskNr<UINT_MAX);
330 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(
m_MaskNr<UINT_MAX);
331 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(
m_MaskNr<UINT_MAX);
366 m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
391 maskstr = wxString::Format(
"%lu", (
unsigned long int)
m_pano->
getImage(imgNr).getMasks().size());
395 maskstr = wxString(
"-");
399 wxString cropstr(
"-");
402 vigra::Rect2D c = img.getCropRect();
403 cropstr.Printf(
"%d,%d,%d,%d", c.left(), c.right(), c.top(), c.bottom());
412 ImageCache::getInstance().softFlush();
418 if (nrItems > nrImages)
420 for (
long i = nrItems - 1; i >= nrImages; i--)
426 if (nrImages >= nrItems)
428 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
437 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
486 if (e.GetKeyCode() == 1 && e.CmdDown())
491 m_imagesListMask->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
505 const bool hasImage = !selectedImages.empty();
540 MainFrame::Get()->SetStatusText(_(
"Create a polygon mask by clicking with the left mouse button on image, set the last point with the right mouse button."),0);
549 wxFileDialog dlg(
this, _(
"Save mask"),
550 wxConfigBase::Get()->Read(wxT(
"/actualPath"), wxT(
"")),
551 wxT(
""), _(
"Mask files (*.msk)|*.msk|All files (*)|*"),
552 wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
553 if (dlg.ShowModal() == wxID_OK)
555 wxString fn = dlg.GetPath();
556 if (fn.Right(4) != wxT(
".msk"))
558 fn.Append(wxT(
".msk"));
559 if (wxFile::Exists(fn))
561 int d = wxMessageBox(wxString::Format(_(
"File %s exists. Overwrite?"),
562 fn.c_str()), _(
"Save mask"),
563 wxYES_NO | wxICON_QUESTION);
569 wxFileName filename = fn;
581 wxFileDialog dlg(
this,_(
"Load mask"),
582 wxConfigBase::Get()->Read(wxT(
"/actualPath"),wxT(
"")),
583 wxT(
""),_(
"Mask files (*.msk)|*.msk|All files (*)|*"),
584 wxFD_OPEN, wxDefaultPosition);
585 if (dlg.ShowModal() != wxID_OK)
590 wxFileName filename(dlg.GetPath());
592 vigra::Size2D maskImageSize;
596 if(maskImageSize.area()==0 || loadedMasks.empty())
598 wxMessageBox(wxString::Format(_(
"Could not parse mask from file %s."),dlg.GetPath().c_str()),_(
"Warning"),wxOK | wxICON_EXCLAMATION,
this);
607 if(dlg.ShowModal()!=wxID_OK)
614 for(
unsigned int i=0;i<loadedMasks.size();i++)
625 std::ostringstream stream;
627 if (wxTheClipboard->Open())
631 wxTheClipboard->SetData(
new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
632 wxTheClipboard->Close();
641 if (wxTheClipboard->Open())
643 vigra::Size2D maskImageSize;
645 if (wxTheClipboard->IsSupported( wxDF_TEXT ))
647 wxTextDataObject
data;
648 wxTheClipboard->GetData(data);
649 std::istringstream stream(std::string(data.GetText().mb_str()));
652 wxTheClipboard->Close();
653 if(maskImageSize.area()==0 || loadedMasks.empty())
664 if(dlg.ShowModal()!=wxID_OK)
671 for(
unsigned int i=0;i<loadedMasks.size();i++)
684 editedMasks.erase(editedMasks.begin()+
m_MaskNr);
694 const wxSize ctrlSize =
m_editImg->GetClientSize();
702 switch (e.GetSelection())
733 m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
735 if (e.GetString() ==
"update_selection")
737 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->SetSelection(e.GetSelection());
743 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_negative"))
746 wxConfigBase::Get()->Write(wxT(
"/MaskEditorPanel/ColourPolygonNegative"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
749 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_positive"))
752 wxConfigBase::Get()->Write(wxT(
"/MaskEditorPanel/ColourPolygonPositive"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
755 if(e.GetId()==XRCID(
"mask_editor_colour_point_selected"))
758 wxConfigBase::Get()->Write(wxT(
"/MaskEditorPanel/ColourPointSelected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
763 wxConfigBase::Get()->Write(wxT(
"/MaskEditorPanel/ColourPointUnselected"),e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
782 m_maskList->InsertItem(i,wxString::Format(wxT(
"%d"),i));
794 if(!restoreSelection && i==oldSelection)
795 m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
809 for(
unsigned int i=0;i<(
unsigned int)
m_maskList->GetItemCount();i++)
811 if(
m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
820 for (
unsigned int i = 0; i < (
unsigned int)
m_imagesListMask->GetItemCount(); i++)
822 if (
m_imagesListMask->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
824 selectedImages.insert(i);
827 return selectedImages;
832 int colNum = e.GetColumn();
833 wxConfigBase::Get()->Write(wxString::Format(
"/ImagesListMask/ColumnWidth%d", colNum),
m_imagesListMask->GetColumnWidth(colNum));
838 int colNum = e.GetColumn();
839 wxConfigBase::Get()->Write( wxString::Format(
"/MaskEditorPanel/ColumnWidth%d",colNum),
m_maskList->GetColumnWidth(colNum) );
852 while (roll > 360) roll-= 360;
853 while (roll < 0) roll += 360;
855 while (pitch > 180) pitch -= 360;
856 while (pitch < -180) pitch += 360;
857 const bool headOver = (pitch > 90 || pitch < -90);
859 if (wxConfig::Get()->Read(
"/CPEditorPanel/AutoRot", 1L))
861 if (roll >= 315 || roll < 45)
867 if (roll >= 45 && roll < 135)
873 if (roll >= 135 && roll < 225)
902 m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
911 if(updateFromImgCtrl)
915 std::vector<HuginBase::SrcPanoImage> srcImgs;
922 for (
auto j : lensImageVector)
926 std::copy(j.begin(), j.end(), std::inserter(imgs, imgs.begin()));
941 srcImgs.push_back(img);
982 wxLogError(_(
"Please enter a valid number"));
1001 wxLogError(_(
"Please enter a valid number"));
1020 wxLogError(_(
"Please enter a valid number"));
1039 wxLogError(_(
"Please enter a valid number"));
1046 m_cropRect.setUpperLeft(vigra::Point2D(0,0));
1047 m_cropRect.setLowerRight(vigra::Point2D(0,0));
1099 wxNotebookEvent dummy;
1106 : wxXmlResourceHandler()
1115 cp->Create(m_parentAsWindow,
1117 GetPosition(), GetSize(),
1118 GetStyle(wxT(
"style")),
1128 return IsOfClass(node, wxT(
"MaskEditorPanel"));
void OnResetButton(wxCommandEvent &e)
ImageRotation
image rotation.
HuginBase::ConstStandardImageVariableGroups * m_imageGroups
void OnSetTop(wxCommandEvent &e)
void SaveMaskToStream(std::ostream &stream, vigra::Size2D imageSize, MaskPolygon &maskToWrite, size_t imgNr)
save the mask into stream
hugin_utils::FDiff2D getRadialDistortionCenter() const
std::vector< UIntSet > UIntSetVector
void UpdateMaskList(bool restoreSelection=false)
updates the display after another image has been selected.
void UpdateCropFromImage()
updates the displayed crop in the text boxes (for dragging)
SrcPanoImage getSrcImage(unsigned imgNr) const
get a description of a source image
wxListCtrl * m_imagesListMask
bool isCircularCrop() const
returns true, if projection requires cicular crop
bool removeObserver(PanoramaObserver *observer)
remove a panorama observer.
void setActiveMask(unsigned int newMask, bool doUpdate=true)
mark mask with image as beeing editing
HuginBase::Panorama * m_pano
void LoadMaskFromStream(std::istream &stream, vigra::Size2D &imageSize, MaskPolygonVector &newMasks, size_t imgNr)
load the mask from stream
void OnMaskPaste(wxCommandEvent &e)
called when user wants to paste a mask from clipboard
void SelectMask(unsigned int newMaskNr)
selects the mask with index newMaskNr in the listbox
void SetUserColourPointUnselected(wxColour newColour)
xrc handler for handling mask editor panel
MaskImageCtrl * m_editImg
HuginBase::MaskPolygonVector getProcessedMask() const
return the processed mask
void OnMaskColumnWidthChange(wxListEvent &e)
called, when column with of mask list box was changed
void OnImageSelect(wxListEvent &e)
called when user selected another image
bool set_contains(const _Container &c, const typename _Container::key_type &key)
virtual bool CanHandle(wxXmlNode *node)
#define DEBUG_ASSERT(cond)
HuginBase::SrcPanoImage::CropMode m_cropMode
include file for the hugin project
void setImage(unsigned int imgNr, bool updateListSelection=false)
sets the image, which is currently edited
vigra::Rect2D getCrop()
returns the current crop rect
void OnMaskLoad(wxCommandEvent &e)
called when user wants to load a mask into the selected image
HuginBase::MaskPolygonVector m_currentMasks
void OnImageListChar(wxKeyEvent &e)
key handler for images list
void OnAutoCenter(wxCommandEvent &e)
wxTextCtrl * m_right_textctrl
void OnSetBottom(wxCommandEvent &e)
void OnSetRight(wxCommandEvent &e)
bool hasMasks() const
returns true, if image has masks associated
void SetUserColourPolygonNegative(wxColour newColour)
sets the colour for different parts
const HuginBase::UIntSet GetSelectedImages()
return the currently selected image(s)
void SetUserColourPointSelected(wxColour newColour)
void setMask(unsigned int maskNr)
sets active mask number, set to UINT_MAX, if no mask is currently editing
std::set< unsigned int > UIntSet
void OnZoom(wxCommandEvent &e)
sets the actual zoom factor
update mask for given image
void setImage(const std::string &filename, HuginBase::MaskPolygonVector newMask, HuginBase::MaskPolygonVector masksToDraw, ImageRotation rot)
set the current image and mask list, this loads also the image from cache
ConstImageVariableGroup & getLenses()
Get the ImageVariableGroup representing the group of lens variables.
UIntSetVector getPartsSet() const
return a vector which contains a HuginBase::UIntSet for each group with the corresponding images numb...
void panoramaImagesChanged(HuginBase::Panorama &pano, const HuginBase::UIntSet &imgNr)
notifies about changes to images
HuginBase::MaskPolygon::MaskType m_defaultMaskType
void OnMaskTypeChange(wxCommandEvent &e)
handler when mask type was changed
void OnImagesColumnWidthChange(wxListEvent &e)
called, when column with of images list box was changed
HuginBase::MaskPolygonVector getNewMask() const
returns the vector of all mask (including new created mask)
std::size_t getNrOfImages() const
number of images.
static MainFrame * Get()
hack.. kind of a pseudo singleton...
void SwitchToCropMode()
switches the controls to crop mode
MaskType
enumeration with type of possible masks
void OnColourChanged(wxColourPickerEvent &e)
event handler for changing colours
IMPLEMENT_DYNAMIC_CLASS(wxTreeListHeaderWindow, wxWindow)
void OnModeChanged(wxNotebookEvent &e)
ImageRotation getCurrentRotation()
returns the current rotation of displayed image
vigra::Point2D m_cropCenter
double getScale()
return scale factor, 0 for autoscale
void UpdateMask()
called when mask where changed in MaskImageCtrl
Make an ImageVariableGroup for lenses and other common concepts.
static GlobalCmdHist & getInstance()
void UpdateCrop(bool updateFromImgCtrl=false)
updated the crop in the Panorama object with the current values from GUI
void SelectSingleImage(wxListCtrl *list, unsigned int imgNr)
void addCommand(PanoCommand *command, bool execute=true)
Adds a command to the history.
wxCheckBox * m_autocenter_cb
void OnMaskSave(wxCommandEvent &e)
called when user wants to save active mask
std::vector< MaskPolygon > MaskPolygonVector
void Init(HuginBase::Panorama *pano)
#define HUGIN_MASK_COLOUR_POINT_UNSELECTED
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxT("panel"))
void selectAllMarkers()
select all points of active mask
Dialog for loading masks.
void setNewMasks(HuginBase::MaskPolygonVector newMasks, HuginBase::MaskPolygonVector masksToDraw)
updates masks for currently selected image
void OnSetLeft(wxCommandEvent &e)
void addObserver(PanoramaObserver *o)
add a panorama observer.
include file for the hugin project
Handle EVT_KILL_FOCUS and convert it to a EVT_TEXT_ENTER event.
wxNotebook * m_maskCropCtrl
virtual ~MaskEditorPanel()
dtor.
options wxIntPtr wxIntPtr sortData std::vector< PanoInfo > * data
void DisplayCrop(int imgNr)
copies the crop information from the Panorama object to GUI
void setScale(double factor)
set the scaling factor for mask editing display.
#define HUGIN_MASK_COLOUR_POINT_SELECTED
void Init(MaskEditorPanel *parent)
void UpdateCropDisplay()
update GUI display
wxTextCtrl * m_bottom_textctrl
void SetMaskMode(bool newMaskMode)
sets the control to mask (newMaskMode=true) or crop (newMaskMode=false) mode
#define HUGIN_MASK_COLOUR_POLYGON_NEGATIVE
MaskImageCtrl::ImageRotation GetRot(const unsigned int imgNr)
determines, if the image should be rotated for display
void OnMaskDelete(wxCommandEvent &e)
called when user wants to delete active mask
void update()
Update part numbers for each variable group.
Definition of mask load dialog.
const SrcPanoImage & getImage(std::size_t nr) const
get a panorama image, counting starts with 0
void UpdateImage(size_t imgNr)
update the list box for the given imgNr
void SetUserColourPolygonPositive(wxColour newColour)
void OnMaskSelect(wxListEvent &e)
called when user selected another mask
void OnMaskAdd(wxCommandEvent &e)
called when user wants to create new polygon
void panoramaChanged(HuginBase::Panorama &pano)
called when the panorama changes and we should update our display
void OnShowActiveMasks(wxCommandEvent &e)
event handler for changing option if active masks should be drawn
#define HUGIN_MASK_COLOUR_POLYGON_POSITIVE
void startNewPolygon()
starts creating a new polygon
void AddMask()
called when new mask added in MaskImageCtrl
wxTextCtrl * m_top_textctrl
All variables of a source image.
void setCrop(HuginBase::SrcPanoImage::CropMode newCropMode, vigra::Rect2D newCropRect, bool isCentered, hugin_utils::FDiff2D center, bool isCircleCrop)
updates the crop mode and crop rect
virtual wxObject * DoCreateResource()
void initValues(const HuginBase::SrcPanoImage image, const HuginBase::MaskPolygonVector newMask, const vigra::Size2D maskSize)
sets the default values
wxTextCtrl * m_left_textctrl
unsigned int GetSelectedMask()
return index of currently selected masks, return UINT_MAX if no mask is selected
void setDrawingActiveMasks(bool newDrawActiveMasks)
set if active masks should be drawn
void OnMaskCopy(wxCommandEvent &e)
called when user wants to copy a mask to clipboard