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
@@ -177,6 +177,15 @@ set(TEST_GUI_DATA
|
||||
image/paste_result_no_background_square_over_circle.png
|
||||
image/wx.png
|
||||
image/wx.ico
|
||||
image/toucan.png
|
||||
image/toucan_hue_0.538.png
|
||||
image/toucan_sat_-0.41.png
|
||||
image/toucan_bright_-0.259.png
|
||||
image/toucan_hsv_0.538_-0.41_-0.259.png
|
||||
image/toucan_light_46.png
|
||||
image/toucan_dis_240.png
|
||||
image/toucan_grey.png
|
||||
image/toucan_mono_255_255_255.png
|
||||
intl/ja/internat.mo
|
||||
intl/ja/internat.po
|
||||
)
|
||||
|
@@ -411,6 +411,9 @@ public:
|
||||
// Convert to disabled (dimmed) image.
|
||||
wxImage ConvertToDisabled(unsigned char brightness = 255) const;
|
||||
|
||||
// Convert the image based on the given lightness.
|
||||
wxImage ChangeLightness(int alpha) const;
|
||||
|
||||
// these routines are slow but safe
|
||||
void SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b );
|
||||
void SetRGB( const wxRect& rect, unsigned char r, unsigned char g, unsigned char b );
|
||||
@@ -555,10 +558,30 @@ public:
|
||||
// Returned value: # of entries in the histogram
|
||||
unsigned long ComputeHistogram( wxImageHistogram &h ) const;
|
||||
|
||||
// Rotates the hue of each pixel of the image. angle is a double in the range
|
||||
// -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees
|
||||
// Rotates the hue of each pixel in the image by angle, which is a double in
|
||||
// the range [-1.0..+1.0], where -1.0 corresponds to -360 degrees and +1.0
|
||||
// corresponds to +360 degrees.
|
||||
void RotateHue(double angle);
|
||||
|
||||
// Changes the saturation of each pixel in the image. factor is a double in
|
||||
// the range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0
|
||||
// corresponds to +100 percent.
|
||||
void ChangeSaturation(double factor);
|
||||
|
||||
// Changes the brightness (value) of each pixel in the image. factor is a
|
||||
// double in the range [-1.0..+1.0], where -1.0 corresponds to -100 percent
|
||||
// and +1.0 corresponds to +100 percent.
|
||||
void ChangeBrightness(double factor);
|
||||
|
||||
// Changes the hue, the saturation and the brightness (value) of each pixel
|
||||
// in the image. angleH is a double in the range [-1.0..+1.0], where -1.0
|
||||
// corresponds to -360 degrees and +1.0 corresponds to +360 degrees, factorS
|
||||
// is a double in the range [-1.0..+1.0], where -1.0 corresponds to -100
|
||||
// percent and +1.0 corresponds to +100 percent and factorV is a double in
|
||||
// the range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0
|
||||
// corresponds to +100 percent.
|
||||
void ChangeHSV(double angleH, double factorS, double factorV);
|
||||
|
||||
static wxList& GetHandlers() { return sm_handlers; }
|
||||
static void AddHandler( wxImageHandler *handler );
|
||||
static void InsertHandler( wxImageHandler *handler );
|
||||
@@ -649,6 +672,10 @@ protected:
|
||||
virtual wxObjectRefData* CreateRefData() const wxOVERRIDE;
|
||||
virtual wxObjectRefData* CloneRefData(const wxObjectRefData* data) const wxOVERRIDE;
|
||||
|
||||
// Helper function used internally by wxImage class only.
|
||||
template <typename T>
|
||||
void ApplyToAllPixels(void (*filter)(wxImage *, unsigned char *, T), T value);
|
||||
|
||||
private:
|
||||
friend class WXDLLIMPEXP_FWD_CORE wxImageHandler;
|
||||
|
||||
|
@@ -897,12 +897,43 @@ public:
|
||||
wxImage Rotate180() const;
|
||||
|
||||
/**
|
||||
Rotates the hue of each pixel in the image by @e angle, which is a double in
|
||||
the range of -1.0 to +1.0, where -1.0 corresponds to -360 degrees and +1.0
|
||||
Rotates the hue of each pixel in the image by @e angle, which is a double
|
||||
in the range [-1.0..+1.0], where -1.0 corresponds to -360 degrees and +1.0
|
||||
corresponds to +360 degrees.
|
||||
*/
|
||||
void RotateHue(double angle);
|
||||
|
||||
/**
|
||||
Changes the saturation of each pixel in the image. factor is a double in
|
||||
the range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0
|
||||
corresponds to +100 percent.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
void ChangeSaturation(double factor);
|
||||
|
||||
/**
|
||||
Changes the brightness (value) of each pixel in the image. factor is a
|
||||
double in the range [-1.0..+1.0], where -1.0 corresponds to -100 percent
|
||||
and +1.0 corresponds to +100 percent.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
void ChangeBrightness(double factor);
|
||||
|
||||
/**
|
||||
Changes the hue, the saturation and the brightness (value) of each pixel
|
||||
in the image. angleH is a double in the range [-1.0..+1.0], where -1.0
|
||||
corresponds to -360 degrees and +1.0 corresponds to +360 degrees, factorS
|
||||
is a double in the range [-1.0..+1.0], where -1.0 corresponds to -100 percent
|
||||
and +1.0 corresponds to +100 percent and factorV is a double in the range
|
||||
[-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0 corresponds
|
||||
to +100 percent.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
void ChangeHSV(double angleH, double factorS, double factorV);
|
||||
|
||||
/**
|
||||
Returns a scaled version of the image.
|
||||
|
||||
@@ -1020,6 +1051,9 @@ public:
|
||||
calculate the greyscale. Defaults to using the standard ITU-T BT.601
|
||||
when converting to YUV, where every pixel equals
|
||||
(R * @a weight_r) + (G * @a weight_g) + (B * @a weight_b).
|
||||
|
||||
@remarks
|
||||
This function calls wxColour::MakeGrey() for each pixel in the image.
|
||||
*/
|
||||
wxImage ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const;
|
||||
|
||||
@@ -1034,15 +1068,35 @@ public:
|
||||
|
||||
The returned image has white colour where the original has @e (r,g,b)
|
||||
colour and black colour everywhere else.
|
||||
|
||||
@remarks
|
||||
This function calls wxColour::MakeMono() for each pixel in the image.
|
||||
*/
|
||||
wxImage ConvertToMono(unsigned char r, unsigned char g, unsigned char b) const;
|
||||
|
||||
/**
|
||||
Returns disabled (dimmed) version of the image.
|
||||
|
||||
@remarks
|
||||
This function calls wxColour::MakeDisabled() for each pixel in the image.
|
||||
|
||||
@since 2.9.0
|
||||
*/
|
||||
wxImage ConvertToDisabled(unsigned char brightness = 255) const;
|
||||
|
||||
/**
|
||||
Returns a changed version of the image based on the given lightness.
|
||||
This utility function simply darkens or lightens a color, based on the
|
||||
specified percentage @a ialpha. @a ialpha of 0 would make the color
|
||||
completely black, 200 completely white and 100 would not change the color.
|
||||
|
||||
@remarks
|
||||
This function calls wxColour::ChangeLightness() for each pixel in the image.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
wxImage ChangeLightness(int alpha) const;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
@@ -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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@@ -1827,119 +1827,89 @@ void wxImage::Replace( unsigned char r1, unsigned char g1, unsigned char b1,
|
||||
}
|
||||
}
|
||||
|
||||
wxImage wxImage::ConvertToGreyscale(void) const
|
||||
wxImage wxImage::ConvertToGreyscale() const
|
||||
{
|
||||
return ConvertToGreyscale(0.299, 0.587, 0.114);
|
||||
}
|
||||
|
||||
// red, green and blue are doubles in the range [0.0..1.0], they are used
|
||||
// internally by DoMakeGrey() only.
|
||||
class WeightValue
|
||||
{
|
||||
public:
|
||||
WeightValue(double r = 0.0, double g = 0.0, double b = 0.0)
|
||||
: red(r), green(g), blue(b) {}
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
};
|
||||
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoMakeGrey(wxImage *image, unsigned char *rgb, WeightValue weight)
|
||||
{
|
||||
if ( !image->HasMask() || rgb[0] != image->GetMaskRed() ||
|
||||
rgb[1] != image->GetMaskGreen() || rgb[2] != image->GetMaskBlue() )
|
||||
wxColour::MakeGrey(rgb, rgb + 1, rgb + 2, weight.red, weight.green, weight.blue);
|
||||
}
|
||||
|
||||
wxImage wxImage::ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const
|
||||
{
|
||||
wxImage image;
|
||||
wxCHECK_MSG(IsOk(), image, "invalid image");
|
||||
|
||||
const int w = M_IMGDATA->m_width;
|
||||
const int h = M_IMGDATA->m_height;
|
||||
size_t size = size_t(w) * h;
|
||||
image.Create(w, h, false);
|
||||
const unsigned char* alpha = M_IMGDATA->m_alpha;
|
||||
if (alpha)
|
||||
{
|
||||
image.SetAlpha();
|
||||
memcpy(image.GetAlpha(), alpha, size);
|
||||
}
|
||||
const unsigned char mask_r = M_IMGDATA->m_maskRed;
|
||||
const unsigned char mask_g = M_IMGDATA->m_maskGreen;
|
||||
const unsigned char mask_b = M_IMGDATA->m_maskBlue;
|
||||
const bool hasMask = M_IMGDATA->m_hasMask;
|
||||
if (hasMask)
|
||||
image.SetMaskColour(mask_r, mask_g, mask_b);
|
||||
|
||||
const unsigned char* src = M_IMGDATA->m_data;
|
||||
unsigned char* dst = image.GetData();
|
||||
while (size--)
|
||||
{
|
||||
unsigned char r = *src++;
|
||||
unsigned char g = *src++;
|
||||
unsigned char b = *src++;
|
||||
if (!hasMask || r != mask_r || g != mask_g || b != mask_b)
|
||||
wxColour::MakeGrey(&r, &g, &b, weight_r, weight_g, weight_b);
|
||||
*dst++ = r;
|
||||
*dst++ = g;
|
||||
*dst++ = b;
|
||||
}
|
||||
wxImage image = *this;
|
||||
image.ApplyToAllPixels(&DoMakeGrey, WeightValue(weight_r, weight_g, weight_b));
|
||||
return image;
|
||||
}
|
||||
|
||||
wxImage wxImage::ConvertToMono( unsigned char r, unsigned char g, unsigned char b ) const
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoMakeMono(wxImage *WXUNUSED(image), unsigned char *rgb, wxImage::RGBValue rgbValue)
|
||||
{
|
||||
wxImage image;
|
||||
const bool on = (rgb[0] == rgbValue.red) && (rgb[1] == rgbValue.green) && (rgb[2] == rgbValue.blue);
|
||||
wxColour::MakeMono(rgb, rgb + 1, rgb + 2, on);
|
||||
}
|
||||
|
||||
wxCHECK_MSG( IsOk(), image, wxT("invalid image") );
|
||||
wxImage wxImage::ConvertToMono(unsigned char r, unsigned char g, unsigned char b) const
|
||||
{
|
||||
wxImage image = *this;
|
||||
|
||||
image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false );
|
||||
|
||||
unsigned char *data = image.GetData();
|
||||
|
||||
wxCHECK_MSG( data, image, wxT("unable to create image") );
|
||||
|
||||
if (M_IMGDATA->m_hasMask)
|
||||
if ( image.HasMask() )
|
||||
{
|
||||
if (M_IMGDATA->m_maskRed == r && M_IMGDATA->m_maskGreen == g &&
|
||||
M_IMGDATA->m_maskBlue == b)
|
||||
image.SetMaskColour( 255, 255, 255 );
|
||||
if ( image.GetMaskRed() == r && image.GetMaskGreen() == g && image.GetMaskBlue() == b)
|
||||
image.SetMaskColour(255, 255, 255);
|
||||
else
|
||||
image.SetMaskColour( 0, 0, 0 );
|
||||
}
|
||||
|
||||
long size = M_IMGDATA->m_height * M_IMGDATA->m_width;
|
||||
|
||||
unsigned char *srcd = M_IMGDATA->m_data;
|
||||
unsigned char *tard = image.GetData();
|
||||
|
||||
for ( long i = 0; i < size; i++, srcd += 3, tard += 3 )
|
||||
{
|
||||
bool on = (srcd[0] == r) && (srcd[1] == g) && (srcd[2] == b);
|
||||
wxColourBase::MakeMono(tard + 0, tard + 1, tard + 2, on);
|
||||
image.SetMaskColour(0, 0, 0);
|
||||
}
|
||||
|
||||
image.ApplyToAllPixels(&DoMakeMono, RGBValue(r, g, b));
|
||||
return image;
|
||||
}
|
||||
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoMakeDisabled(wxImage *image, unsigned char *rgb, unsigned char brightness)
|
||||
{
|
||||
if ( !image->HasMask() || rgb[0] != image->GetMaskRed() ||
|
||||
rgb[1] != image->GetMaskGreen() || rgb[2] != image->GetMaskBlue() )
|
||||
wxColour::MakeDisabled(rgb, rgb + 1, rgb + 2, brightness);
|
||||
}
|
||||
|
||||
wxImage wxImage::ConvertToDisabled(unsigned char brightness) const
|
||||
{
|
||||
wxImage image;
|
||||
wxCHECK_MSG(IsOk(), image, "invalid image");
|
||||
wxImage image = *this;
|
||||
image.ApplyToAllPixels(&DoMakeDisabled, brightness);
|
||||
return image;
|
||||
}
|
||||
|
||||
const int w = M_IMGDATA->m_width;
|
||||
const int h = M_IMGDATA->m_height;
|
||||
size_t size = size_t(w) * h;
|
||||
image.Create(w, h, false);
|
||||
const unsigned char* alpha = M_IMGDATA->m_alpha;
|
||||
if (alpha)
|
||||
{
|
||||
image.SetAlpha();
|
||||
memcpy(image.GetAlpha(), alpha, size);
|
||||
}
|
||||
const unsigned char mask_r = M_IMGDATA->m_maskRed;
|
||||
const unsigned char mask_g = M_IMGDATA->m_maskGreen;
|
||||
const unsigned char mask_b = M_IMGDATA->m_maskBlue;
|
||||
const bool hasMask = M_IMGDATA->m_hasMask;
|
||||
if (hasMask)
|
||||
image.SetMaskColour(mask_r, mask_g, mask_b);
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoChangeLightness(wxImage *image, unsigned char *rgb, int alpha)
|
||||
{
|
||||
if ( !image->HasMask() || rgb[0] != image->GetMaskRed() ||
|
||||
rgb[1] != image->GetMaskGreen() || rgb[2] != image->GetMaskBlue() )
|
||||
wxColour::ChangeLightness(rgb, rgb + 1, rgb + 2, alpha);
|
||||
}
|
||||
|
||||
const unsigned char* src = M_IMGDATA->m_data;
|
||||
unsigned char* dst = image.GetData();
|
||||
while (size--)
|
||||
{
|
||||
unsigned char r = *src++;
|
||||
unsigned char g = *src++;
|
||||
unsigned char b = *src++;
|
||||
if (!hasMask || r != mask_r || g != mask_g || b != mask_b)
|
||||
wxColour::MakeDisabled(&r, &g, &b, brightness);
|
||||
*dst++ = r;
|
||||
*dst++ = g;
|
||||
*dst++ = b;
|
||||
}
|
||||
wxImage wxImage::ChangeLightness(int alpha) const
|
||||
{
|
||||
wxASSERT(alpha >= 0 && alpha <= 200);
|
||||
wxImage image = *this;
|
||||
image.ApplyToAllPixels(&DoChangeLightness, alpha);
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -3323,45 +3293,126 @@ wxImage::RGBValue wxImage::HSVtoRGB(const HSVValue& hsv)
|
||||
(unsigned char)wxRound(blue * 255.0));
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotates the hue of each pixel of the image. angle is a double in the range
|
||||
* -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees
|
||||
*/
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoRotateHue(wxImage *WXUNUSED(image), unsigned char *rgb, double angle)
|
||||
{
|
||||
wxImage::RGBValue rgbValue(rgb[0], rgb[1], rgb[2]);
|
||||
wxImage::HSVValue hsvValue = wxImage::RGBtoHSV(rgbValue);
|
||||
|
||||
hsvValue.hue = hsvValue.hue + angle;
|
||||
|
||||
if (hsvValue.hue > 1.0)
|
||||
hsvValue.hue = hsvValue.hue - 1.0;
|
||||
else if (hsvValue.hue < 0.0)
|
||||
hsvValue.hue = hsvValue.hue + 1.0;
|
||||
|
||||
rgbValue = wxImage::HSVtoRGB(hsvValue);
|
||||
rgb[0] = rgbValue.red;
|
||||
rgb[1] = rgbValue.green;
|
||||
rgb[2] = rgbValue.blue;
|
||||
}
|
||||
|
||||
// Rotates the hue of each pixel in the image by angle, which is a double in the
|
||||
// range [-1.0..+1.0], where -1.0 corresponds to -360 degrees and +1.0 corresponds
|
||||
// to +360 degrees.
|
||||
void wxImage::RotateHue(double angle)
|
||||
{
|
||||
AllocExclusive();
|
||||
if ( wxIsNullDouble(angle) )
|
||||
return;
|
||||
|
||||
unsigned long count;
|
||||
wxImage::HSVValue hsv;
|
||||
wxImage::RGBValue rgb;
|
||||
wxASSERT(angle >= -1.0 && angle <= 1.0);
|
||||
ApplyToAllPixels(&DoRotateHue, angle);
|
||||
}
|
||||
|
||||
wxASSERT (angle >= -1.0 && angle <= 1.0);
|
||||
count = M_IMGDATA->m_width * M_IMGDATA->m_height;
|
||||
if ( count > 0 && !wxIsNullDouble(angle) )
|
||||
{
|
||||
unsigned char* srcBytePtr;
|
||||
unsigned char* dstBytePtr;
|
||||
srcBytePtr = M_IMGDATA->m_data;
|
||||
dstBytePtr = srcBytePtr;
|
||||
do
|
||||
{
|
||||
rgb.red = *srcBytePtr++;
|
||||
rgb.green = *srcBytePtr++;
|
||||
rgb.blue = *srcBytePtr++;
|
||||
hsv = RGBtoHSV(rgb);
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoChangeSaturation(wxImage *WXUNUSED(image), unsigned char *rgb, double factor)
|
||||
{
|
||||
wxImage::RGBValue rgbValue(rgb[0], rgb[1], rgb[2]);
|
||||
wxImage::HSVValue hsvValue = wxImage::RGBtoHSV(rgbValue);
|
||||
|
||||
hsv.hue = hsv.hue + angle;
|
||||
if (hsv.hue > 1.0)
|
||||
hsv.hue = hsv.hue - 1.0;
|
||||
else if (hsv.hue < 0.0)
|
||||
hsv.hue = hsv.hue + 1.0;
|
||||
hsvValue.saturation += hsvValue.saturation * factor;
|
||||
|
||||
rgb = HSVtoRGB(hsv);
|
||||
*dstBytePtr++ = rgb.red;
|
||||
*dstBytePtr++ = rgb.green;
|
||||
*dstBytePtr++ = rgb.blue;
|
||||
} while (--count != 0);
|
||||
}
|
||||
if (hsvValue.saturation > 1.0)
|
||||
hsvValue.saturation = 1.0;
|
||||
else if (hsvValue.saturation < 0.0)
|
||||
hsvValue.saturation = 0.0;
|
||||
|
||||
rgbValue = wxImage::HSVtoRGB(hsvValue);
|
||||
rgb[0] = rgbValue.red;
|
||||
rgb[1] = rgbValue.green;
|
||||
rgb[2] = rgbValue.blue;
|
||||
}
|
||||
|
||||
// Changes the saturation of each pixel in the image. factor is a double in the
|
||||
// range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0 corresponds
|
||||
// to +100 percent.
|
||||
void wxImage::ChangeSaturation(double factor)
|
||||
{
|
||||
if ( wxIsNullDouble(factor) )
|
||||
return;
|
||||
|
||||
wxASSERT(factor >= -1.0 && factor <= 1.0);
|
||||
ApplyToAllPixels(&DoChangeSaturation, factor);
|
||||
}
|
||||
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoChangeBrightness(wxImage *WXUNUSED(image), unsigned char *rgb, double factor)
|
||||
{
|
||||
wxImage::RGBValue rgbValue(rgb[0], rgb[1], rgb[2]);
|
||||
wxImage::HSVValue hsvValue = wxImage::RGBtoHSV(rgbValue);
|
||||
|
||||
hsvValue.value += hsvValue.value * factor;
|
||||
|
||||
if (hsvValue.value > 1.0)
|
||||
hsvValue.value = 1.0;
|
||||
else if (hsvValue.value < 0.0)
|
||||
hsvValue.value = 0.0;
|
||||
|
||||
rgbValue = wxImage::HSVtoRGB(hsvValue);
|
||||
rgb[0] = rgbValue.red;
|
||||
rgb[1] = rgbValue.green;
|
||||
rgb[2] = rgbValue.blue;
|
||||
}
|
||||
|
||||
// Changes the brightness (value) of each pixel in the image. factor is a double
|
||||
// in the range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0
|
||||
// corresponds to +100 percent.
|
||||
void wxImage::ChangeBrightness(double factor)
|
||||
{
|
||||
if ( wxIsNullDouble(factor) )
|
||||
return;
|
||||
|
||||
wxASSERT(factor >= -1.0 && factor <= 1.0);
|
||||
ApplyToAllPixels(&DoChangeBrightness, factor);
|
||||
}
|
||||
|
||||
// TODO-C++11: Replace with a lambda function.
|
||||
void DoChangeHSV(wxImage *image, unsigned char *rgb, wxImage::HSVValue hsvValue)
|
||||
{
|
||||
if ( !wxIsNullDouble(hsvValue.hue) )
|
||||
DoRotateHue(image, rgb, hsvValue.hue);
|
||||
|
||||
if ( !wxIsNullDouble(hsvValue.saturation) )
|
||||
DoChangeSaturation(image, rgb, hsvValue.saturation);
|
||||
|
||||
if ( !wxIsNullDouble(hsvValue.value) )
|
||||
DoChangeBrightness(image, rgb, hsvValue.value);
|
||||
}
|
||||
|
||||
// Changes the hue, the saturation and the brightness (value) of each pixel in
|
||||
// the image. angleH is a double in the range [-1.0..+1.0], where -1.0 corresponds
|
||||
// to -360 degrees and +1.0 corresponds to +360 degrees, factorS is a double in
|
||||
// the range [-1.0..+1.0], where -1.0 corresponds to -100 percent and +1.0
|
||||
// corresponds to +100 percent and factorV is a double in the range [-1.0..+1.0],
|
||||
// where -1.0 corresponds to -100 percent and +1.0 corresponds to +100 percent.
|
||||
void wxImage::ChangeHSV(double angleH, double factorS, double factorV)
|
||||
{
|
||||
if ( wxIsNullDouble(angleH) && wxIsNullDouble(factorS) && wxIsNullDouble(factorV) )
|
||||
return;
|
||||
|
||||
wxASSERT(angleH >= -1.0 && angleH <= 1.0 && factorS >= -1.0 &&
|
||||
factorS <= 1.0 && factorV >= -1.0 && factorV <= 1.0);
|
||||
ApplyToAllPixels(&DoChangeHSV, HSVValue(angleH, factorS, factorV));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -3857,9 +3908,20 @@ wxImage wxImage::Rotate(double angle,
|
||||
return rotated;
|
||||
}
|
||||
|
||||
// Helper function used internally by wxImage class only.
|
||||
template <typename T>
|
||||
void wxImage::ApplyToAllPixels(void (*filter)(wxImage *, unsigned char *, T), T value)
|
||||
{
|
||||
AllocExclusive();
|
||||
|
||||
const size_t size = GetWidth() * GetHeight();
|
||||
unsigned char *data = GetData();
|
||||
|
||||
|
||||
for ( size_t i = 0; i < size; i++, data += 3 )
|
||||
{
|
||||
(*filter)(this, data, value);
|
||||
}
|
||||
}
|
||||
|
||||
// A module to allow wxImage initialization/cleanup
|
||||
// without calling these functions from app.cpp or from
|
||||
|
@@ -554,7 +554,7 @@ data:
|
||||
|
||||
data-images:
|
||||
@mkdir -p image
|
||||
@for f in horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico; do \
|
||||
@for f in horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png; do \
|
||||
if test ! -f image/$$f -a ! -d image/$$f ; \
|
||||
then x=yep ; \
|
||||
else x=`find $(srcdir)/image/$$f -newer image/$$f -print` ; \
|
||||
|
@@ -2200,6 +2200,55 @@ TEST_CASE("wxImage::XPM", "[image][xpm]")
|
||||
CHECK( wxIcon(dummy_xpm).IsOk() );
|
||||
}
|
||||
|
||||
TEST_CASE("wxImage::ChangeColours", "[image]")
|
||||
{
|
||||
wxImage original;
|
||||
REQUIRE(original.LoadFile("image/toucan.png", wxBITMAP_TYPE_PNG));
|
||||
|
||||
wxImage test;
|
||||
wxImage expected;
|
||||
|
||||
test = original;
|
||||
test.RotateHue(0.538);
|
||||
REQUIRE(expected.LoadFile("image/toucan_hue_0.538.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test.ChangeSaturation(-0.41);
|
||||
REQUIRE(expected.LoadFile("image/toucan_sat_-0.41.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test.ChangeBrightness(-0.259);
|
||||
REQUIRE(expected.LoadFile("image/toucan_bright_-0.259.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test.ChangeHSV(0.538, -0.41, -0.259);
|
||||
REQUIRE(expected.LoadFile("image/toucan_hsv_0.538_-0.41_-0.259.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test = test.ChangeLightness(46);
|
||||
REQUIRE(expected.LoadFile("image/toucan_light_46.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test = test.ConvertToDisabled(240);
|
||||
REQUIRE(expected.LoadFile("image/toucan_dis_240.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test = test.ConvertToGreyscale();
|
||||
REQUIRE(expected.LoadFile("image/toucan_grey.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
|
||||
test = original;
|
||||
test = test.ConvertToMono(255, 255, 255);
|
||||
REQUIRE(expected.LoadFile("image/toucan_mono_255_255_255.png", wxBITMAP_TYPE_PNG));
|
||||
CHECK_THAT(test, RGBSameAs(expected));
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: add lots of more tests to wxImage functions
|
||||
*/
|
||||
|
BIN
tests/image/toucan.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
tests/image/toucan_bright_-0.259.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/image/toucan_dis_240.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/image/toucan_grey.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
tests/image/toucan_hsv_0.538_-0.41_-0.259.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/image/toucan_hue_0.538.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/image/toucan_light_46.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
tests/image/toucan_mono_255_255_255.png
Normal file
After Width: | Height: | Size: 5.9 KiB |
BIN
tests/image/toucan_sat_-0.41.png
Normal file
After Width: | Height: | Size: 11 KiB |
@@ -529,7 +529,7 @@ data:
|
||||
|
||||
data-images:
|
||||
if not exist image mkdir image
|
||||
for %f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png) do if not exist image\%f copy .\image\%f image
|
||||
for %f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png) do if not exist image\%f copy .\image\%f image
|
||||
|
||||
fr:
|
||||
if not exist $(OBJS)\intl\fr mkdir $(OBJS)\intl\fr
|
||||
|
@@ -554,7 +554,7 @@ data:
|
||||
|
||||
data-images:
|
||||
if not exist image mkdir image
|
||||
for %%f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico) do if not exist image\%%f copy .\image\%%f image
|
||||
for %%f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png) do if not exist image\%%f copy .\image\%%f image
|
||||
|
||||
fr:
|
||||
if not exist $(OBJS)\intl\fr mkdir $(OBJS)\intl\fr
|
||||
|
@@ -988,7 +988,7 @@ data:
|
||||
|
||||
data-images:
|
||||
if not exist image mkdir image
|
||||
for %f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico) do if not exist image\%f copy .\image\%f image
|
||||
for %f in (horse_grey.bmp horse_grey_flipped.bmp horse_rle4.bmp horse_rle4_flipped.bmp horse_rle8.bmp horse_rle8_flipped.bmp horse_bicubic_50x50.png horse_bicubic_100x100.png horse_bicubic_150x150.png horse_bicubic_300x300.png horse_bilinear_50x50.png horse_bilinear_100x100.png horse_bilinear_150x150.png horse_bilinear_300x300.png horse_box_average_50x50.png horse_box_average_100x100.png horse_box_average_150x150.png horse_box_average_300x300.png cross_bicubic_256x256.png cross_bilinear_256x256.png cross_box_average_256x256.png cross_nearest_neighb_256x256.png paste_input_background.png paste_input_black.png paste_input_overlay_transparent_border_opaque_square.png paste_input_overlay_transparent_border_semitransparent_circle.png paste_input_overlay_transparent_border_semitransparent_square.png paste_result_background_plus_circle_plus_square.png paste_result_background_plus_overlay_transparent_border_opaque_square.png paste_result_background_plus_overlay_transparent_border_semitransparent_square.png paste_result_no_background_square_over_circle.png wx.png wx.ico toucan.png toucan_hue_0.538.png toucan_sat_-0.41.png toucan_bright_-0.259.png toucan_hsv_0.538_-0.41_-0.259.png toucan_light_46.png toucan_dis_240.png toucan_grey.png toucan_mono_255_255_255.png) do if not exist image\%f copy .\image\%f image
|
||||
|
||||
fr:
|
||||
if not exist $(OBJS)\intl\fr mkdir $(OBJS)\intl\fr
|
||||
|
@@ -384,6 +384,16 @@
|
||||
|
||||
wx.png
|
||||
wx.ico
|
||||
|
||||
toucan.png
|
||||
toucan_hue_0.538.png
|
||||
toucan_sat_-0.41.png
|
||||
toucan_bright_-0.259.png
|
||||
toucan_hsv_0.538_-0.41_-0.259.png
|
||||
toucan_light_46.png
|
||||
toucan_dis_240.png
|
||||
toucan_grey.png
|
||||
toucan_mono_255_255_255.png
|
||||
</files>
|
||||
</wx-data>
|
||||
|
||||
|