From 4da0bfc20b4e87eea8b508a92eb7b5967bbee53a Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Fri, 2 Sep 2011 21:43:56 +0200 Subject: [PATCH] Eeschema: bitmap editor dialog: some enhancements --- common/class_bitmap_base.cpp | 4 +- common/dialogs/dialog_image_editor.cpp | 85 +++++- common/dialogs/dialog_image_editor.fbp | 272 +++++++++++++++++++- common/dialogs/dialog_image_editor.h | 8 +- common/dialogs/dialog_image_editor_base.cpp | 22 +- common/dialogs/dialog_image_editor_base.h | 8 +- include/class_bitmap_base.h | 20 ++ 7 files changed, 405 insertions(+), 14 deletions(-) diff --git a/common/class_bitmap_base.cpp b/common/class_bitmap_base.cpp index ed85fa252a..c645b40705 100644 --- a/common/class_bitmap_base.cpp +++ b/common/class_bitmap_base.cpp @@ -236,7 +236,7 @@ void BITMAP_BASE::Mirror( bool aVertically ) if( m_image ) { *m_image = m_image->Mirror( not aVertically ); - *m_bitmap = wxBitmap( *m_image ); + RebuildBitmap(); } } @@ -246,7 +246,7 @@ void BITMAP_BASE::Rotate( bool aRotateCCW ) if( m_image ) { *m_image = m_image->Rotate90( aRotateCCW ); - *m_bitmap = wxBitmap( *m_image ); + RebuildBitmap(); } } diff --git a/common/dialogs/dialog_image_editor.cpp b/common/dialogs/dialog_image_editor.cpp index 78738fa97e..48b81ec3f2 100644 --- a/common/dialogs/dialog_image_editor.cpp +++ b/common/dialogs/dialog_image_editor.cpp @@ -40,6 +40,8 @@ DIALOG_IMAGE_EDITOR::DIALOG_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem : DIALOG_IMAGE_EDITOR_BASE( aParent ) { m_workingImage = new BITMAP_BASE( * aItem ); + m_lastImage = NULL; + m_buttonUndoLast->Enable( false ); wxString msg; msg.Printf( wxT("%f"), m_workingImage->m_Scale ); m_textCtrlScale->SetValue( msg );; @@ -53,28 +55,106 @@ DIALOG_IMAGE_EDITOR::DIALOG_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem SetFocus(); } +void DIALOG_IMAGE_EDITOR::OnUndoLastChange( wxCommandEvent& event ) +{ + BITMAP_BASE * tmp = m_workingImage; + m_workingImage = m_lastImage; + delete tmp; + m_buttonUndoLast->Enable( false ); + m_lastImage = NULL; + m_panelDraw->Refresh(); +} + void DIALOG_IMAGE_EDITOR::OnMirrorX_click( wxCommandEvent& event ) { - + delete m_lastImage; + m_lastImage = new BITMAP_BASE( * m_workingImage ); + m_buttonUndoLast->Enable( true ); + m_buttonUndoLast->Enable( true ); m_workingImage->Mirror( true ); m_panelDraw->Refresh(); } void DIALOG_IMAGE_EDITOR::OnMirrorY_click( wxCommandEvent& event ) { + delete m_lastImage; + m_lastImage = new BITMAP_BASE( * m_workingImage ); + m_buttonUndoLast->Enable( true ); m_workingImage->Mirror( false ); m_panelDraw->Refresh(); } void DIALOG_IMAGE_EDITOR::OnRotateClick( wxCommandEvent& event ) { + delete m_lastImage; + m_lastImage = new BITMAP_BASE( * m_workingImage ); + m_buttonUndoLast->Enable( true ); m_workingImage->Rotate( false ); m_panelDraw->Refresh(); } +void DIALOG_IMAGE_EDITOR::OnGreyScaleConvert( wxCommandEvent& event ) +{ + delete m_lastImage; + m_lastImage = new BITMAP_BASE( * m_workingImage ); + m_buttonUndoLast->Enable( true ); + wxImage& image = *m_workingImage->GetImageData(); + image = image.ConvertToGreyscale(); + m_workingImage->RebuildBitmap(); + m_panelDraw->Refresh(); +} + +void DIALOG_IMAGE_EDITOR::OnHalfSize( wxCommandEvent& event ) +{ + delete m_lastImage; + m_lastImage = new BITMAP_BASE( * m_workingImage ); + m_buttonUndoLast->Enable( true ); + wxSize psize = m_workingImage->GetSizePixels(); + wxImage& image = *m_workingImage->GetImageData(); + + image = image.Scale(psize.x/2, psize.y/2, wxIMAGE_QUALITY_HIGH); + m_workingImage->RebuildBitmap(); + m_panelDraw->Refresh(); +} + +/* Test params values correctness + * Currently scale value must give an actual image + * > MIN_SIZE pixels and < MAX_SIZE pixels + */ +bool DIALOG_IMAGE_EDITOR::CheckValues() +{ + #define MIN_SIZE 16 + #define MAX_SIZE 6000 + double tmp; + wxString msg = m_textCtrlScale->GetValue(); + // Test number correctness + if( ! msg.ToDouble( &tmp ) ) + { + wxMessageBox( _("Incorrect scale number" ) ); + return false; + } + + // Test value correctness + wxSize psize = m_workingImage->GetSizePixels(); + if ( (psize.x * tmp) < MIN_SIZE || (psize.y * tmp) < MIN_SIZE ) + { + wxMessageBox( _("Scale is too small for this image" ) ); + return false; + } + if ( (psize.x * tmp) > MAX_SIZE || (psize.y * tmp) > MAX_SIZE ) + { + wxMessageBox( _("Scale is too large for this image" ) ); + return false; + } + + return true; +} + void DIALOG_IMAGE_EDITOR::OnOK_Button( wxCommandEvent& aEvent ) { - EndModal( wxID_OK ); + if( CheckValues() ) + EndModal( wxID_OK ); + return; } void DIALOG_IMAGE_EDITOR::OnCancel_Button( wxCommandEvent& aEvent ) @@ -97,7 +177,6 @@ void DIALOG_IMAGE_EDITOR::TransfertToImage(BITMAP_BASE* aItem ) { wxString msg = m_textCtrlScale->GetValue(); msg.ToDouble( &m_workingImage->m_Scale ); - m_textCtrlScale->SetValue( msg ); aItem->ImportData( m_workingImage ); } diff --git a/common/dialogs/dialog_image_editor.fbp b/common/dialogs/dialog_image_editor.fbp index 7be9af1293..27ec5a178e 100644 --- a/common/dialogs/dialog_image_editor.fbp +++ b/common/dialogs/dialog_image_editor.fbp @@ -69,7 +69,7 @@ Resizable 1 - 340,256 + 340,299 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER Image Editor @@ -236,7 +236,7 @@ none 5 - wxEXPAND|wxALL + wxEXPAND|wxTOP|wxRIGHT|wxLEFT 0 1 @@ -324,7 +324,7 @@ 5 - wxEXPAND|wxALL + wxEXPAND|wxTOP|wxRIGHT|wxLEFT 0 1 @@ -412,7 +412,7 @@ 5 - wxALL|wxEXPAND + wxEXPAND|wxALL 0 1 @@ -498,6 +498,270 @@ + + 5 + wxEXPAND|wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Grey + + + 0 + + + 0 + + 1 + m_buttonGrey + 1 + + + protected + 1 + + + Resizable + + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnGreyScaleConvert + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + 1 + 0 + 1 + + 1 + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Half Size + + + 0 + + + 0 + + 1 + m_buttonHalfSize + 1 + + + protected + 1 + + + Resizable + + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnHalfSize + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Undo Last + + + 0 + + + 0 + + 1 + m_buttonUndoLast + 1 + + + protected + 1 + + + Resizable + + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnUndoLastChange + + + + + + + + + + + + + + + + + + + + + + + + + 5 wxTOP|wxRIGHT|wxLEFT diff --git a/common/dialogs/dialog_image_editor.h b/common/dialogs/dialog_image_editor.h index 64592cca5e..874622f357 100644 --- a/common/dialogs/dialog_image_editor.h +++ b/common/dialogs/dialog_image_editor.h @@ -35,7 +35,9 @@ class DIALOG_IMAGE_EDITOR : public DIALOG_IMAGE_EDITOR_BASE { private: - BITMAP_BASE* m_workingImage; + BITMAP_BASE* m_workingImage; // The copy of BITMAP_BASE to be edited + BITMAP_BASE* m_lastImage; // the saved BITMAP_BASE before a new change. + // Used to undo the last change public: DIALOG_IMAGE_EDITOR( wxWindow* aParent, BITMAP_BASE* aItem ); @@ -51,12 +53,16 @@ public: void TransfertToImage( BITMAP_BASE* aItem ); private: + void OnUndoLastChange( wxCommandEvent& event ); + void OnGreyScaleConvert( wxCommandEvent& event ); + void OnHalfSize( wxCommandEvent& event ); void OnMirrorX_click( wxCommandEvent& event ); void OnMirrorY_click( wxCommandEvent& event ); void OnRotateClick( wxCommandEvent& event ); void OnOK_Button( wxCommandEvent& aEvent ); void OnCancel_Button( wxCommandEvent& aEvent ); void OnRedrawPanel( wxPaintEvent& event ); + bool CheckValues(); }; diff --git a/common/dialogs/dialog_image_editor_base.cpp b/common/dialogs/dialog_image_editor_base.cpp index 7b05b29e44..613343fe4b 100644 --- a/common/dialogs/dialog_image_editor_base.cpp +++ b/common/dialogs/dialog_image_editor_base.cpp @@ -31,13 +31,23 @@ DIALOG_IMAGE_EDITOR_BASE::DIALOG_IMAGE_EDITOR_BASE( wxWindow* parent, wxWindowID bSizerRight = new wxBoxSizer( wxVERTICAL ); m_buttonMirrorX = new wxButton( this, wxID_ANY, _("Mirror X"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerRight->Add( m_buttonMirrorX, 0, wxEXPAND|wxALL, 5 ); + bSizerRight->Add( m_buttonMirrorX, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); m_buttonMirrorY = new wxButton( this, wxID_ANY, _("Mirror Y"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerRight->Add( m_buttonMirrorY, 0, wxEXPAND|wxALL, 5 ); + bSizerRight->Add( m_buttonMirrorY, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); m_buttonRotate = new wxButton( this, wxID_ANY, _("Rotate"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizerRight->Add( m_buttonRotate, 0, wxALL|wxEXPAND, 5 ); + bSizerRight->Add( m_buttonRotate, 0, wxEXPAND|wxALL, 5 ); + + m_buttonGrey = new wxButton( this, wxID_ANY, _("Grey"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerRight->Add( m_buttonGrey, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_buttonHalfSize = new wxButton( this, wxID_ANY, _("Half Size"), wxDefaultPosition, wxDefaultSize, 0 ); + m_buttonHalfSize->SetDefault(); + bSizerRight->Add( m_buttonHalfSize, 0, wxALL|wxEXPAND, 5 ); + + m_buttonUndoLast = new wxButton( this, wxID_ANY, _("Undo Last"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizerRight->Add( m_buttonUndoLast, 0, wxALL|wxEXPAND, 5 ); m_staticTextScale = new wxStaticText( this, wxID_ANY, _("Image Scale:"), wxDefaultPosition, wxDefaultSize, 0 ); m_staticTextScale->Wrap( -1 ); @@ -70,6 +80,9 @@ DIALOG_IMAGE_EDITOR_BASE::DIALOG_IMAGE_EDITOR_BASE( wxWindow* parent, wxWindowID m_buttonMirrorX->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnMirrorX_click ), NULL, this ); m_buttonMirrorY->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnMirrorY_click ), NULL, this ); m_buttonRotate->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnRotateClick ), NULL, this ); + m_buttonGrey->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnGreyScaleConvert ), NULL, this ); + m_buttonHalfSize->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnHalfSize ), NULL, this ); + m_buttonUndoLast->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnUndoLastChange ), NULL, this ); m_sdbSizer1Cancel->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnCancel_Button ), NULL, this ); m_sdbSizer1OK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnOK_Button ), NULL, this ); } @@ -81,6 +94,9 @@ DIALOG_IMAGE_EDITOR_BASE::~DIALOG_IMAGE_EDITOR_BASE() m_buttonMirrorX->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnMirrorX_click ), NULL, this ); m_buttonMirrorY->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnMirrorY_click ), NULL, this ); m_buttonRotate->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnRotateClick ), NULL, this ); + m_buttonGrey->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnGreyScaleConvert ), NULL, this ); + m_buttonHalfSize->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnHalfSize ), NULL, this ); + m_buttonUndoLast->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnUndoLastChange ), NULL, this ); m_sdbSizer1Cancel->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnCancel_Button ), NULL, this ); m_sdbSizer1OK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_IMAGE_EDITOR_BASE::OnOK_Button ), NULL, this ); diff --git a/common/dialogs/dialog_image_editor_base.h b/common/dialogs/dialog_image_editor_base.h index b4e2784a2b..e7f888ee33 100644 --- a/common/dialogs/dialog_image_editor_base.h +++ b/common/dialogs/dialog_image_editor_base.h @@ -38,6 +38,9 @@ class DIALOG_IMAGE_EDITOR_BASE : public wxDialog wxButton* m_buttonMirrorX; wxButton* m_buttonMirrorY; wxButton* m_buttonRotate; + wxButton* m_buttonGrey; + wxButton* m_buttonHalfSize; + wxButton* m_buttonUndoLast; wxStaticText* m_staticTextScale; wxTextCtrl* m_textCtrlScale; wxStdDialogButtonSizer* m_sdbSizer1; @@ -49,13 +52,16 @@ class DIALOG_IMAGE_EDITOR_BASE : public wxDialog virtual void OnMirrorX_click( wxCommandEvent& event ) { event.Skip(); } virtual void OnMirrorY_click( wxCommandEvent& event ) { event.Skip(); } virtual void OnRotateClick( wxCommandEvent& event ) { event.Skip(); } + virtual void OnGreyScaleConvert( wxCommandEvent& event ) { event.Skip(); } + virtual void OnHalfSize( wxCommandEvent& event ) { event.Skip(); } + virtual void OnUndoLastChange( wxCommandEvent& event ) { event.Skip(); } virtual void OnCancel_Button( wxCommandEvent& event ) { event.Skip(); } virtual void OnOK_Button( wxCommandEvent& event ) { event.Skip(); } public: - DIALOG_IMAGE_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Image Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 340,256 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_IMAGE_EDITOR_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Image Editor"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 340,299 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_IMAGE_EDITOR_BASE(); }; diff --git a/include/class_bitmap_base.h b/include/class_bitmap_base.h index 6d75a100cc..8a53674154 100644 --- a/include/class_bitmap_base.h +++ b/include/class_bitmap_base.h @@ -72,6 +72,14 @@ public: BITMAP_BASE( const wxPoint& pos = wxPoint( 0, 0 ) ); */ double GetPixelScaleFactor() { return m_pixelScaleFactor; } void SetPixelScaleFactor( double aSF ) { m_pixelScaleFactor = aSF; } + wxImage* GetImageData() { return m_image; } + + /* + * Function RebuildBitmap + * Rebuild the internal bitmap used to draw/plot image + * must be called after a m_image change + */ + void RebuildBitmap() { *m_bitmap = wxBitmap( *m_image ); } /** * Function ImportData @@ -102,6 +110,18 @@ public: BITMAP_BASE( const wxPoint& pos = wxPoint( 0, 0 ) ); */ wxSize GetSize() const; + /** + * Function GetSizePixels + * @returns the size in pixels of the image + */ + wxSize GetSizePixels() const + { + if( m_image ) + return wxSize( m_image->GetWidth(), m_image->GetHeight() ); + else + return wxSize(0,0); + } + /** * Function GetBoundingBox * returns the orthogonal, bounding box of this object for display