Add wxImage Change{Saturation,Brightness,HSV,Lightness}()
Add more functions for manipulating wxImage colours. Show using them in the same and add new unit tests for them. This is a squashed commit of branch 'tomay3000/image-lightness'. Closes https://github.com/wxWidgets/wxWidgets/pull/2310
This commit is contained in:
@@ -27,6 +27,8 @@
|
||||
#include "wx/scopedptr.h"
|
||||
#include "wx/stopwatch.h"
|
||||
#include "wx/versioninfo.h"
|
||||
#include "wx/artprov.h"
|
||||
#include "wx/spinctrl.h"
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
#include "wx/dataobj.h"
|
||||
@@ -78,6 +80,7 @@ public:
|
||||
void OnNewFrameHiDPI(wxCommandEvent&);
|
||||
void OnImageInfo( wxCommandEvent &event );
|
||||
void OnThumbnail( wxCommandEvent &event );
|
||||
void OnFilters(wxCommandEvent& event);
|
||||
void OnUpdateNewFrameHiDPI(wxUpdateUIEvent&);
|
||||
|
||||
#ifdef wxHAVE_RAW_BITMAP
|
||||
@@ -104,7 +107,10 @@ private:
|
||||
// image or were cancelled by user
|
||||
static wxString LoadUserImage(wxImage& image);
|
||||
|
||||
private:
|
||||
friend class MyFiltersFrame;
|
||||
|
||||
private:
|
||||
wxDECLARE_DYNAMIC_CLASS(MyFrame);
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
@@ -651,6 +657,272 @@ private:
|
||||
|
||||
#endif // wxHAVE_RAW_BITMAP
|
||||
|
||||
class MyFiltersFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
MyFiltersFrame(wxWindow *parent)
|
||||
: wxFrame(parent, wxID_ANY, "Image filters test")
|
||||
{
|
||||
wxMenu *menuImage = new wxMenu;
|
||||
|
||||
menuImage->Append(wxID_OPEN, "&Open...\tCtrl-O", "Load a user defined image");
|
||||
menuImage->Append(wxID_RESET, "&Reset\tCtrl-R", "Reset all the image filters");
|
||||
menuImage->Append(wxID_CLOSE, "&Close\tCtrl-Q", "Close this frame");
|
||||
|
||||
wxMenuBar *menuBar = new wxMenuBar();
|
||||
menuBar->Append(menuImage, "&Image");
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
wxSizerFlags sizerFlags1(1);
|
||||
sizerFlags1.Border().Expand();
|
||||
|
||||
wxSizerFlags sizerFlags2;
|
||||
sizerFlags2.Border().Expand();
|
||||
|
||||
wxSizerFlags sizerFlags3;
|
||||
sizerFlags3.Border().Center();
|
||||
|
||||
wxSizerFlags sizerFlags4;
|
||||
sizerFlags4.Border();
|
||||
|
||||
wxStaticBoxSizer *sizerHue = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Hue (°)")), wxVERTICAL);
|
||||
m_sliderHue = new wxSlider(sizerHue->GetStaticBox(), wxID_ANY, 0, -360, 360,
|
||||
wxDefaultPosition, wxDefaultSize, wxSL_HORIZONTAL | wxSL_LABELS);
|
||||
sizerHue->Add(m_sliderHue, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerSaturation = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Saturation (%)")), wxVERTICAL);
|
||||
m_sliderSaturation = new wxSlider(sizerSaturation->GetStaticBox(), wxID_ANY,
|
||||
0, -100, 100, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_HORIZONTAL | wxSL_LABELS);
|
||||
sizerSaturation->Add(m_sliderSaturation, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerBrightness = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Brightness (value) (%)")),
|
||||
wxVERTICAL);
|
||||
m_sliderBrightness = new wxSlider(sizerBrightness->GetStaticBox(), wxID_ANY,
|
||||
0, -100, 100, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_HORIZONTAL | wxSL_LABELS);
|
||||
sizerBrightness->Add(m_sliderBrightness, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerLightness = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Lightness")),
|
||||
wxVERTICAL);
|
||||
m_sliderLightness = new wxSlider(sizerLightness->GetStaticBox(), wxID_ANY,
|
||||
100, 0, 200, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_HORIZONTAL | wxSL_LABELS);
|
||||
sizerLightness->Add(m_sliderLightness, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerDisabled = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Disabled")), wxVERTICAL);
|
||||
m_checkDisabled = new wxCheckBox(sizerDisabled->GetStaticBox(), wxID_ANY,
|
||||
wxS("Convert to disabled"));
|
||||
m_sliderDisabled = new wxSlider(sizerDisabled->GetStaticBox(), wxID_ANY,
|
||||
255, 0, 255, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_HORIZONTAL | wxSL_LABELS);
|
||||
sizerDisabled->Add(m_checkDisabled, sizerFlags4);
|
||||
sizerDisabled->Add(m_sliderDisabled, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerGrey = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Greyscale")), wxVERTICAL);
|
||||
m_checkGrey = new wxCheckBox(sizerGrey->GetStaticBox(), wxID_ANY,
|
||||
wxS("Convert to greyscale"));
|
||||
wxBoxSizer *sizer1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_spinGreyWeightR = new wxSpinCtrlDouble(sizerGrey->GetStaticBox(),
|
||||
wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 1, 0.299, 0.001);
|
||||
m_spinGreyWeightG = new wxSpinCtrlDouble(sizerGrey->GetStaticBox(),
|
||||
wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 1, 0.587, 0.001);
|
||||
m_spinGreyWeightB = new wxSpinCtrlDouble(sizerGrey->GetStaticBox(),
|
||||
wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 1, 0.114, 0.001);
|
||||
sizer1->AddStretchSpacer();
|
||||
sizer1->Add(new wxStaticText(sizerGrey->GetStaticBox(), wxID_ANY,
|
||||
wxS("Red weight:")), sizerFlags3);
|
||||
sizer1->Add(m_spinGreyWeightR, sizerFlags3);
|
||||
sizer1->Add(new wxStaticText(sizerGrey->GetStaticBox(), wxID_ANY,
|
||||
wxS("Green weight:")), sizerFlags3);
|
||||
sizer1->Add(m_spinGreyWeightG, sizerFlags3);
|
||||
sizer1->Add(new wxStaticText(sizerGrey->GetStaticBox(), wxID_ANY,
|
||||
wxS("Blue weight:")), sizerFlags3);
|
||||
sizer1->Add(m_spinGreyWeightB, sizerFlags3);
|
||||
sizer1->AddStretchSpacer();
|
||||
sizerGrey->Add(m_checkGrey, sizerFlags4);
|
||||
sizerGrey->Add(sizer1, sizerFlags2);
|
||||
|
||||
wxStaticBoxSizer *sizerMono = new wxStaticBoxSizer(new wxStaticBox(this,
|
||||
wxID_ANY, wxS("Monochrome")), wxVERTICAL);
|
||||
m_checkMono = new wxCheckBox(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxS("Convert to monochrome"));
|
||||
wxBoxSizer *sizer2 = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_spinMonoR = new wxSpinCtrl(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, 0, 255, 0);
|
||||
m_spinMonoG = new wxSpinCtrl(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, 0, 255, 0);
|
||||
m_spinMonoB = new wxSpinCtrl(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, 0, 255, 0);
|
||||
sizer2->AddStretchSpacer();
|
||||
sizer2->Add(new wxStaticText(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxS("Red:")), sizerFlags3);
|
||||
sizer2->Add(m_spinMonoR, sizerFlags3);
|
||||
sizer2->Add(new wxStaticText(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxS("Green:")), sizerFlags3);
|
||||
sizer2->Add(m_spinMonoG, sizerFlags3);
|
||||
sizer2->Add(new wxStaticText(sizerMono->GetStaticBox(), wxID_ANY,
|
||||
wxS("Blue:")), sizerFlags3);
|
||||
sizer2->Add(m_spinMonoB, sizerFlags3);
|
||||
sizer2->AddStretchSpacer();
|
||||
sizerMono->Add(m_checkMono, sizerFlags4);
|
||||
sizerMono->Add(sizer2, sizerFlags2);
|
||||
|
||||
wxBoxSizer *sizerLeft = new wxBoxSizer(wxVERTICAL);
|
||||
sizerLeft->Add(sizerHue, sizerFlags2);
|
||||
sizerLeft->Add(sizerSaturation, sizerFlags2);
|
||||
sizerLeft->Add(sizerBrightness, sizerFlags2);
|
||||
sizerLeft->Add(sizerLightness, sizerFlags2);
|
||||
|
||||
wxBoxSizer *sizerRight = new wxBoxSizer(wxVERTICAL);
|
||||
sizerRight->Add(sizerDisabled, sizerFlags2);
|
||||
sizerRight->Add(sizerGrey, sizerFlags2);
|
||||
sizerRight->Add(sizerMono, sizerFlags2);
|
||||
|
||||
wxBitmap bitmap = wxArtProvider::GetBitmap(wxART_INFORMATION, wxART_BUTTON,
|
||||
wxSize(256, 256));
|
||||
m_image = bitmap.ConvertToImage();
|
||||
|
||||
m_stcBitmap = new wxStaticBitmap(this, wxID_ANY, bitmap);
|
||||
wxBoxSizer *sizerTop = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizerTop->AddStretchSpacer();
|
||||
sizerTop->Add(m_stcBitmap, sizerFlags1);
|
||||
sizerTop->AddStretchSpacer();
|
||||
|
||||
sizerFlags1.Border(0);
|
||||
|
||||
wxBoxSizer *sizerBottom = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizerBottom->Add(sizerLeft, sizerFlags1);
|
||||
sizerBottom->Add(sizerRight, sizerFlags1);
|
||||
|
||||
wxBoxSizer *sizerMain = new wxBoxSizer(wxVERTICAL);
|
||||
sizerMain->Add(sizerTop, sizerFlags1);
|
||||
sizerMain->Add(sizerBottom, sizerFlags2);
|
||||
|
||||
SetSizer(sizerMain);
|
||||
CreateStatusBar();
|
||||
|
||||
// Bind Events
|
||||
Bind(wxEVT_MENU, &MyFiltersFrame::OnNewImage, this, wxID_OPEN);
|
||||
Bind(wxEVT_MENU, &MyFiltersFrame::OnReset, this, wxID_RESET);
|
||||
Bind(wxEVT_MENU, &MyFiltersFrame::OnClose, this, wxID_CLOSE);
|
||||
m_sliderHue->Bind(wxEVT_SLIDER, &MyFiltersFrame::OnFilter, this);
|
||||
m_sliderSaturation->Bind(wxEVT_SLIDER, &MyFiltersFrame::OnFilter, this);
|
||||
m_sliderBrightness->Bind(wxEVT_SLIDER, &MyFiltersFrame::OnFilter, this);
|
||||
m_sliderLightness->Bind(wxEVT_SLIDER, &MyFiltersFrame::OnFilter, this);
|
||||
m_checkDisabled->Bind(wxEVT_CHECKBOX, &MyFiltersFrame::OnFilter, this);
|
||||
m_sliderDisabled->Bind(wxEVT_SLIDER, &MyFiltersFrame::OnFilter, this);
|
||||
m_checkGrey->Bind(wxEVT_CHECKBOX, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinGreyWeightR->Bind(wxEVT_SPINCTRLDOUBLE, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinGreyWeightG->Bind(wxEVT_SPINCTRLDOUBLE, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinGreyWeightB->Bind(wxEVT_SPINCTRLDOUBLE, &MyFiltersFrame::OnFilter, this);
|
||||
m_checkMono->Bind(wxEVT_CHECKBOX, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinMonoR->Bind(wxEVT_SPINCTRL, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinMonoG->Bind(wxEVT_SPINCTRL, &MyFiltersFrame::OnFilter, this);
|
||||
m_spinMonoB->Bind(wxEVT_SPINCTRL, &MyFiltersFrame::OnFilter, this);
|
||||
}
|
||||
|
||||
private:
|
||||
wxStaticBitmap *m_stcBitmap;
|
||||
wxSlider *m_sliderHue;
|
||||
wxSlider *m_sliderSaturation;
|
||||
wxSlider *m_sliderBrightness;
|
||||
wxSlider *m_sliderLightness;
|
||||
wxCheckBox *m_checkDisabled;
|
||||
wxSlider *m_sliderDisabled;
|
||||
wxCheckBox *m_checkGrey;
|
||||
wxSpinCtrlDouble *m_spinGreyWeightR;
|
||||
wxSpinCtrlDouble *m_spinGreyWeightG;
|
||||
wxSpinCtrlDouble *m_spinGreyWeightB;
|
||||
wxCheckBox *m_checkMono;
|
||||
wxSpinCtrl *m_spinMonoR;
|
||||
wxSpinCtrl *m_spinMonoG;
|
||||
wxSpinCtrl *m_spinMonoB;
|
||||
wxImage m_image;
|
||||
|
||||
protected:
|
||||
void OnNewImage(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxImage image;
|
||||
wxString filename = static_cast<MyFrame *>(GetParent())->LoadUserImage(image);
|
||||
|
||||
if ( !filename.empty() )
|
||||
{
|
||||
m_image = image;
|
||||
DoFilter();
|
||||
}
|
||||
}
|
||||
|
||||
void OnReset(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_stcBitmap->SetBitmap(m_image);
|
||||
m_sliderHue->SetValue(0);
|
||||
m_sliderSaturation->SetValue(0);
|
||||
m_sliderBrightness->SetValue(0);
|
||||
m_sliderLightness->SetValue(100);
|
||||
m_checkDisabled->SetValue(false);
|
||||
m_sliderDisabled->SetValue(255);
|
||||
m_checkGrey->SetValue(false);
|
||||
m_spinGreyWeightR->SetValue(0.299);
|
||||
m_spinGreyWeightG->SetValue(0.587);
|
||||
m_spinGreyWeightB->SetValue(0.114);
|
||||
m_checkMono->SetValue(false);
|
||||
m_spinMonoR->SetValue(0);
|
||||
m_spinMonoG->SetValue(0);
|
||||
m_spinMonoB->SetValue(0);
|
||||
}
|
||||
|
||||
void OnClose(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
Close(true);
|
||||
}
|
||||
|
||||
virtual void OnFilter(wxEvent& WXUNUSED(event))
|
||||
{
|
||||
DoFilter();
|
||||
}
|
||||
|
||||
void DoFilter()
|
||||
{
|
||||
wxImage image = m_image;
|
||||
image.RotateHue(m_sliderHue->GetValue() / 360.);
|
||||
image.ChangeSaturation(m_sliderSaturation->GetValue() / 100.);
|
||||
image.ChangeBrightness(m_sliderBrightness->GetValue() / 100.);
|
||||
image = image.ChangeLightness(m_sliderLightness->GetValue());
|
||||
|
||||
if ( m_checkDisabled->IsChecked() )
|
||||
image = image.ConvertToDisabled(m_sliderDisabled->GetValue());
|
||||
|
||||
if ( m_checkGrey->IsChecked() )
|
||||
{
|
||||
image = image.ConvertToGreyscale(m_spinGreyWeightR->GetValue(),
|
||||
m_spinGreyWeightG->GetValue(),
|
||||
m_spinGreyWeightB->GetValue());
|
||||
}
|
||||
|
||||
if ( m_checkMono->IsChecked() )
|
||||
{
|
||||
image = image.ConvertToMono(m_spinMonoR->GetValue(),
|
||||
m_spinMonoG->GetValue(),
|
||||
m_spinMonoB->GetValue());
|
||||
}
|
||||
|
||||
m_stcBitmap->SetBitmap(image);
|
||||
Layout();
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// implementations
|
||||
@@ -700,7 +972,8 @@ enum
|
||||
ID_GRAPHICS,
|
||||
ID_SHOWTHUMBNAIL,
|
||||
ID_COPY_IMAGE,
|
||||
ID_PASTE_IMAGE
|
||||
ID_PASTE_IMAGE,
|
||||
ID_FILTERS
|
||||
};
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS( MyFrame, wxFrame );
|
||||
@@ -711,6 +984,7 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU (ID_NEW_HIDPI, MyFrame::OnNewFrameHiDPI)
|
||||
EVT_MENU (ID_INFO, MyFrame::OnImageInfo)
|
||||
EVT_MENU (ID_SHOWTHUMBNAIL, MyFrame::OnThumbnail)
|
||||
EVT_MENU (ID_FILTERS, MyFrame::OnFilters)
|
||||
#ifdef wxHAVE_RAW_BITMAP
|
||||
EVT_MENU (ID_SHOWRAW, MyFrame::OnTestRawBitmap)
|
||||
#endif
|
||||
@@ -750,6 +1024,9 @@ MyFrame::MyFrame()
|
||||
menuImage->Append( ID_SHOWTHUMBNAIL, "Test &thumbnail...\tCtrl-T",
|
||||
"Test scaling the image during load (try with JPEG)");
|
||||
menuImage->AppendSeparator();
|
||||
menuImage->Append(ID_FILTERS, "Test image &filters...\tCtrl-F",
|
||||
"Test applying different image filters");
|
||||
menuImage->AppendSeparator();
|
||||
menuImage->Append( ID_ABOUT, "&About\tF1");
|
||||
menuImage->AppendSeparator();
|
||||
menuImage->Append( ID_QUIT, "E&xit\tCtrl-Q");
|
||||
@@ -1088,6 +1365,11 @@ void MyFrame::OnThumbnail( wxCommandEvent &WXUNUSED(event) )
|
||||
#endif // wxUSE_FILEDLG
|
||||
}
|
||||
|
||||
void MyFrame::OnFilters(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
(new MyFiltersFrame(this))->Show();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// MyApp
|
||||
//-----------------------------------------------------------------------------
|
||||
|
Reference in New Issue
Block a user