39 #include <wx/clipbrd.h>
58 if (! wxPanel::Create(parent,
id, pos, size, style, name))
66 wxXmlResource::Get()->LoadPanel(
this,
"mask_panel");
67 wxPanel * panel = XRCCTRL(*
this,
"mask_panel", wxPanel);
69 wxBoxSizer *topsizer =
new wxBoxSizer( wxVERTICAL );
70 topsizer->Add(panel, 1, wxEXPAND, 0);
81 m_imagesListMask->InsertColumn(2, _(
"Number of masks"), wxLIST_FORMAT_RIGHT, 120);
89 wxConfigBase* config = wxConfigBase::Get();
93 int width = config->Read(wxString::Format(
"/ImagesListMask/ColumnWidth%d", j), -1);
100 m_maskList = XRCCTRL(*
this,
"mask_editor_mask_list", wxListCtrl);
101 m_maskList->InsertColumn( 0,
"#", wxLIST_FORMAT_RIGHT, 35);
102 m_maskList->InsertColumn( 1, _(
"Mask type"), wxLIST_FORMAT_LEFT, 120);
107 m_maskCropCtrl = XRCCTRL(*
this,
"mask_editor_mask_crop_notebook", wxNotebook);
114 for (
int j=0; j <
m_maskList->GetColumnCount() ; j++ )
117 int width = config->Read(wxString::Format(
"/MaskEditorPanel/ColumnWidth%d", j ), -1);
122 config->Read(
"/MaskEditorPanel/ShowActiveMasks",&activeMasks,
false);
123 XRCCTRL(*
this,
"mask_editor_show_active_masks",wxCheckBox)->SetValue(activeMasks);
127 wxColour defaultColour;
129 wxColour colour = config->Read(
"/MaskEditorPanel/ColourPolygonNegative", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
130 XRCCTRL(*
this,
"mask_editor_colour_polygon_negative",wxColourPickerCtrl)->SetColour(colour);
133 colour = config->Read(
"/MaskEditorPanel/ColourPolygonPositive", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
134 XRCCTRL(*
this,
"mask_editor_colour_polygon_positive",wxColourPickerCtrl)->SetColour(colour);
137 colour = config->Read(
"/MaskEditorPanel/ColourPointSelected", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
138 XRCCTRL(*
this,
"mask_editor_colour_point_selected",wxColourPickerCtrl)->SetColour(colour);
141 colour = config->Read(
"/MaskEditorPanel/ColourPointUnselected", defaultColour.GetAsString(wxC2S_HTML_SYNTAX));
142 XRCCTRL(*
this,
"mask_editor_colour_point_unselected",wxColourPickerCtrl)->SetColour(colour);
147 m_maskType = XRCCTRL(*
this,
"mask_editor_choice_masktype", wxChoice);
153 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->Disable();
154 XRCCTRL(*
this,
"mask_editor_add", wxButton)->Disable();
155 XRCCTRL(*
this,
"mask_editor_load", wxButton)->Disable();
156 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Disable();
157 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Disable();
158 XRCCTRL(*
this,
"mask_editor_paste", wxButton)->Disable();
159 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Disable();
166 m_cropLens = XRCCTRL(*
this,
"crop_all_images_lens", wxCheckBox);
168 bool doCropImagesLens;
169 config->Read(
"/MaskEditorPanel/CropImagesLens", &doCropImagesLens,
true);
192 wxAcceleratorEntry entries[2];
193 entries[0].Set(wxACCEL_CMD,(
int)
'C',XRCID(
"mask_editor_copy"));
194 entries[1].Set(wxACCEL_CMD,(
int)
'V',XRCID(
"mask_editor_paste"));
195 wxAcceleratorTable accel(2, entries);
196 SetAcceleratorTable(accel);
199 wxCommandEvent dummy;
200 dummy.SetInt(XRCCTRL(*
this,
"mask_editor_choice_zoom",wxChoice)->GetSelection());
229 wxConfigBase* config = wxConfigBase::Get();
230 config->Write(
"/MaskEditorPanel/ShowActiveMasks",XRCCTRL(*
this,
"mask_editor_show_active_masks",wxCheckBox)->GetValue());
232 config->Write(
"/MaskEditorPanel/CropImagesLens",
m_cropLens->GetValue());
257 unsigned int nrItems = list->GetItemCount();
259 for (
unsigned int i = 0; i < nrItems; i++)
265 list->SetItemState(i, 0, wxLIST_STATE_SELECTED);
267 list->SetItemState(imgNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
273 bool restoreMaskSelection=(imgNr==
GetImgNr());
274 bool updateImage=
true;
276 if (imgNr == UINT_MAX)
286 updateImage=(
m_File!=image.getFilename());
288 m_File=image.getFilename();
293 m_File=image.getFilename();
296 masksToDraw=image.getActiveMasks();
307 bool enableCtrl=(imgNr<UINT_MAX);
308 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
309 XRCCTRL(*
this,
"mask_editor_add", wxButton)->Enable(enableCtrl);
310 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
311 XRCCTRL(*
this,
"mask_editor_load", wxButton)->Enable(enableCtrl);
312 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
313 XRCCTRL(*
this,
"mask_editor_paste", wxButton)->Enable(enableCtrl);
314 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
317 ImageCache::getInstance().softFlush();
318 if(updateListSelection)
330 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(
m_MaskNr<UINT_MAX);
331 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(
m_MaskNr<UINT_MAX);
332 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(
m_MaskNr<UINT_MAX);
367 m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
392 maskstr = wxString::Format(
"%lu", (
unsigned long int)
m_pano->
getImage(imgNr).getMasks().size());
396 maskstr = wxString(
"-");
400 wxString cropstr(
"-");
403 vigra::Rect2D c = img.getCropRect();
404 cropstr.Printf(
"%d,%d,%d,%d", c.left(), c.right(), c.top(), c.bottom());
413 ImageCache::getInstance().softFlush();
419 if (nrItems > nrImages)
421 for (
long i = nrItems - 1; i >= nrImages; i--)
427 if (nrImages >= nrItems)
429 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
438 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
487 if (e.GetKeyCode() == 1 && e.CmdDown())
492 m_imagesListMask->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
506 const bool hasImage = !selectedImages.empty();
541 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);
550 wxFileDialog dlg(
this, _(
"Save mask"),
551 wxConfigBase::Get()->Read(
"/actualPath", wxEmptyString),
552 wxEmptyString, _(
"Mask files (*.msk)|*.msk|All files (*)|*"),
553 wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
554 if (dlg.ShowModal() == wxID_OK)
556 wxString fn = dlg.GetPath();
557 if (fn.Right(4) !=
".msk")
560 if (wxFile::Exists(fn))
568 wxFileName filename = fn;
580 wxFileDialog dlg(
this,_(
"Load mask"),
581 wxConfigBase::Get()->Read(
"/actualPath",wxEmptyString),
582 wxEmptyString,_(
"Mask files (*.msk)|*.msk|All files (*)|*"),
583 wxFD_OPEN, wxDefaultPosition);
584 if (dlg.ShowModal() != wxID_OK)
589 wxFileName filename(dlg.GetPath());
591 vigra::Size2D maskImageSize;
595 if(maskImageSize.area()==0 || loadedMasks.empty())
597 hugin_utils::HuginMessageBox(wxString::Format(_(
"Could not parse mask from file %s."), dlg.GetPath()), _(
"Hugin"), wxOK | wxICON_EXCLAMATION,
this);
606 if(dlg.ShowModal()!=wxID_OK)
613 for(
unsigned int i=0;i<loadedMasks.size();i++)
624 std::ostringstream stream;
626 if (wxTheClipboard->Open())
630 wxTheClipboard->SetData(
new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
631 wxTheClipboard->Close();
640 if (wxTheClipboard->Open())
642 vigra::Size2D maskImageSize;
644 if (wxTheClipboard->IsSupported( wxDF_TEXT ))
646 wxTextDataObject
data;
647 wxTheClipboard->GetData(data);
648 std::istringstream stream(std::string(data.GetText().mb_str()));
651 wxTheClipboard->Close();
652 if(maskImageSize.area()==0 || loadedMasks.empty())
663 if(dlg.ShowModal()!=wxID_OK)
670 for(
unsigned int i=0;i<loadedMasks.size();i++)
683 editedMasks.erase(editedMasks.begin()+
m_MaskNr);
693 const wxSize ctrlSize =
m_editImg->GetClientSize();
701 switch (e.GetSelection())
732 m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
734 if (e.GetString() ==
"update_selection")
736 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->SetSelection(e.GetSelection());
742 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_negative"))
745 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPolygonNegative",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
748 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_positive"))
751 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPolygonPositive",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
754 if(e.GetId()==XRCID(
"mask_editor_colour_point_selected"))
757 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPointSelected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
762 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPointUnselected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
781 m_maskList->InsertItem(i,wxString::Format(
"%d",i));
793 if(!restoreSelection && i==oldSelection)
794 m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
808 for(
unsigned int i=0;i<(
unsigned int)
m_maskList->GetItemCount();i++)
810 if(
m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
819 for (
unsigned int i = 0; i < (
unsigned int)
m_imagesListMask->GetItemCount(); i++)
821 if (
m_imagesListMask->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
823 selectedImages.insert(i);
826 return selectedImages;
831 int colNum = e.GetColumn();
832 wxConfigBase::Get()->Write(wxString::Format(
"/ImagesListMask/ColumnWidth%d", colNum),
m_imagesListMask->GetColumnWidth(colNum));
837 int colNum = e.GetColumn();
838 wxConfigBase::Get()->Write( wxString::Format(
"/MaskEditorPanel/ColumnWidth%d",colNum),
m_maskList->GetColumnWidth(colNum) );
851 while (roll > 360) roll-= 360;
852 while (roll < 0) roll += 360;
854 while (pitch > 180) pitch -= 360;
855 while (pitch < -180) pitch += 360;
856 const bool headOver = (pitch > 90 || pitch < -90);
858 if (wxConfig::Get()->Read(
"/CPEditorPanel/AutoRot", 1L))
860 if (roll >= 315 || roll < 45)
866 if (roll >= 45 && roll < 135)
872 if (roll >= 135 && roll < 225)
901 m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
910 if(updateFromImgCtrl)
914 std::vector<HuginBase::SrcPanoImage> srcImgs;
921 for (
auto j : lensImageVector)
925 std::copy(j.begin(), j.end(), std::inserter(imgs, imgs.begin()));
940 srcImgs.push_back(img);
981 wxLogError(_(
"Please enter a valid number"));
1000 wxLogError(_(
"Please enter a valid number"));
1019 wxLogError(_(
"Please enter a valid number"));
1038 wxLogError(_(
"Please enter a valid number"));
1045 m_cropRect.setUpperLeft(vigra::Point2D(0,0));
1046 m_cropRect.setLowerRight(vigra::Point2D(0,0));
1098 wxNotebookEvent dummy;
1105 : wxXmlResourceHandler()
1114 cp->Create(m_parentAsWindow,
1116 GetPosition(), GetSize(),
1127 return IsOfClass(node,
"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
bool AskUserOverwrite(const wxString &filename, const wxString &caption, wxWindow *parent)
ask user if the given file should be overwritten, return true if the user confirmed the overwritting ...
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
void selectAllMarkers()
select all points of active mask
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name="panel")
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
int HuginMessageBox(const wxString &message, const wxString &caption, int style, wxWindow *parent)
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