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 if (imgNr != UINT_MAX)
269 list->SetItemState(imgNr, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED, wxLIST_STATE_SELECTED | wxLIST_STATE_FOCUSED);
276 bool restoreMaskSelection=(imgNr==
GetImgNr());
277 bool updateImage=
true;
279 if (imgNr == UINT_MAX)
289 updateImage=(
m_File!=image.getFilename());
291 m_File=image.getFilename();
296 m_File=image.getFilename();
299 masksToDraw=image.getActiveMasks();
310 bool enableCtrl=(imgNr<UINT_MAX);
311 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->Enable(enableCtrl);
312 XRCCTRL(*
this,
"mask_editor_add", wxButton)->Enable(enableCtrl);
313 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
314 XRCCTRL(*
this,
"mask_editor_load", wxButton)->Enable(enableCtrl);
315 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
316 XRCCTRL(*
this,
"mask_editor_paste", wxButton)->Enable(enableCtrl);
317 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(enableCtrl &&
m_MaskNr<UINT_MAX);
320 ImageCache::getInstance().softFlush();
321 if(updateListSelection)
333 XRCCTRL(*
this,
"mask_editor_delete", wxButton)->Enable(
m_MaskNr<UINT_MAX);
334 XRCCTRL(*
this,
"mask_editor_save", wxButton)->Enable(
m_MaskNr<UINT_MAX);
335 XRCCTRL(*
this,
"mask_editor_copy", wxButton)->Enable(
m_MaskNr<UINT_MAX);
370 m_maskList->SetItemState(newMaskNr, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
395 maskstr = wxString::Format(
"%lu", (
unsigned long int)
m_pano->
getImage(imgNr).getMasks().size());
399 maskstr = wxString(
"-");
403 wxString cropstr(
"-");
406 vigra::Rect2D c = img.getCropRect();
407 cropstr.Printf(
"%d,%d,%d,%d", c.left(), c.right(), c.top(), c.bottom());
416 ImageCache::getInstance().softFlush();
422 if (nrItems > nrImages)
424 for (
long i = nrItems - 1; i >= nrImages; i--)
430 if (nrImages >= nrItems)
432 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
441 for (HuginBase::UIntSet::const_iterator it = changed.begin(); it != changed.end(); ++it)
490 if (e.GetKeyCode() == 1 && e.CmdDown())
495 m_imagesListMask->SetItemState(i, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
509 const bool hasImage = !selectedImages.empty();
544 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);
553 wxFileDialog dlg(
this, _(
"Save mask"),
554 wxConfigBase::Get()->Read(
"/actualPath", wxEmptyString),
555 wxEmptyString, _(
"Mask files (*.msk)|*.msk|All files (*)|*"),
556 wxFD_SAVE | wxFD_OVERWRITE_PROMPT, wxDefaultPosition);
557 if (dlg.ShowModal() == wxID_OK)
559 wxString fn = dlg.GetPath();
560 if (fn.Right(4) !=
".msk")
563 if (wxFile::Exists(fn))
571 wxFileName filename = fn;
583 wxFileDialog dlg(
this,_(
"Load mask"),
584 wxConfigBase::Get()->Read(
"/actualPath",wxEmptyString),
585 wxEmptyString,_(
"Mask files (*.msk)|*.msk|All files (*)|*"),
586 wxFD_OPEN, wxDefaultPosition);
587 if (dlg.ShowModal() != wxID_OK)
592 wxFileName filename(dlg.GetPath());
594 vigra::Size2D maskImageSize;
598 if(maskImageSize.area()==0 || loadedMasks.empty())
600 hugin_utils::HuginMessageBox(wxString::Format(_(
"Could not parse mask from file %s."), dlg.GetPath()), _(
"Hugin"), wxOK | wxICON_EXCLAMATION,
this);
609 if(dlg.ShowModal()!=wxID_OK)
616 for(
unsigned int i=0;i<loadedMasks.size();i++)
627 std::ostringstream stream;
629 if (wxTheClipboard->Open())
633 wxTheClipboard->SetData(
new wxTextDataObject(wxString(stream.str().c_str(),wxConvLocal)));
634 wxTheClipboard->Close();
643 if (wxTheClipboard->Open())
645 vigra::Size2D maskImageSize;
647 if (wxTheClipboard->IsSupported( wxDF_TEXT ))
649 wxTextDataObject
data;
650 wxTheClipboard->GetData(data);
651 std::istringstream stream(std::string(data.GetText().mb_str()));
654 wxTheClipboard->Close();
655 if(maskImageSize.area()==0 || loadedMasks.empty())
666 if(dlg.ShowModal()!=wxID_OK)
673 for(
unsigned int i=0;i<loadedMasks.size();i++)
686 editedMasks.erase(editedMasks.begin()+
m_MaskNr);
696 const wxSize ctrlSize =
m_editImg->GetClientSize();
704 switch (e.GetSelection())
735 m_editImg->Scroll(posX*factor - ctrlSize.GetWidth() / 2, posY*factor - ctrlSize.GetHeight() / 2);
737 if (e.GetString() ==
"update_selection")
739 XRCCTRL(*
this,
"mask_editor_choice_zoom", wxChoice)->SetSelection(e.GetSelection());
745 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_negative"))
748 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPolygonNegative",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
751 if(e.GetId()==XRCID(
"mask_editor_colour_polygon_positive"))
754 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPolygonPositive",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
757 if(e.GetId()==XRCID(
"mask_editor_colour_point_selected"))
760 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPointSelected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
765 wxConfigBase::Get()->Write(
"/MaskEditorPanel/ColourPointUnselected",e.GetColour().GetAsString(wxC2S_HTML_SYNTAX));
784 m_maskList->InsertItem(i,wxString::Format(
"%d",i));
796 if(!restoreSelection && i==oldSelection)
797 m_maskList->SetItemState(i,0, wxLIST_STATE_SELECTED);
811 for(
unsigned int i=0;i<(
unsigned int)
m_maskList->GetItemCount();i++)
813 if(
m_maskList->GetItemState(i,wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
822 for (
unsigned int i = 0; i < (
unsigned int)
m_imagesListMask->GetItemCount(); i++)
824 if (
m_imagesListMask->GetItemState(i, wxLIST_STATE_SELECTED) & wxLIST_STATE_SELECTED)
826 selectedImages.insert(i);
829 return selectedImages;
834 int colNum = e.GetColumn();
835 wxConfigBase::Get()->Write(wxString::Format(
"/ImagesListMask/ColumnWidth%d", colNum),
m_imagesListMask->GetColumnWidth(colNum));
840 int colNum = e.GetColumn();
841 wxConfigBase::Get()->Write( wxString::Format(
"/MaskEditorPanel/ColumnWidth%d",colNum),
m_maskList->GetColumnWidth(colNum) );
854 while (roll > 360) roll-= 360;
855 while (roll < 0) roll += 360;
857 while (pitch > 180) pitch -= 360;
858 while (pitch < -180) pitch += 360;
859 const bool headOver = (pitch > 90 || pitch < -90);
861 if (wxConfig::Get()->Read(
"/CPEditorPanel/AutoRot", 1L))
863 if (roll >= 315 || roll < 45)
869 if (roll >= 45 && roll < 135)
875 if (roll >= 135 && roll < 225)
904 m_cropCenter = vigra::Point2D(img.getSize().width()/2 + dx, img.getSize().height()/2 + dy);
913 if(updateFromImgCtrl)
917 std::vector<HuginBase::SrcPanoImage> srcImgs;
924 for (
auto j : lensImageVector)
928 std::copy(j.begin(), j.end(), std::inserter(imgs, imgs.begin()));
943 srcImgs.push_back(img);
984 wxLogError(_(
"Please enter a valid number"));
1003 wxLogError(_(
"Please enter a valid number"));
1022 wxLogError(_(
"Please enter a valid number"));
1041 wxLogError(_(
"Please enter a valid number"));
1048 m_cropRect.setUpperLeft(vigra::Point2D(0,0));
1049 m_cropRect.setLowerRight(vigra::Point2D(0,0));
1120 wxNotebookEvent dummy;
1127 : wxXmlResourceHandler()
1136 cp->Create(m_parentAsWindow,
1138 GetPosition(), GetSize(),
1149 return IsOfClass(node,
"MaskEditorPanel");
void OnResetButton(wxCommandEvent &e)
ImageRotation
image rotation.
void SetSingleSelection(bool singleSelMode)
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