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:
Tomay
2021-05-01 14:03:04 +02:00
committed by Vadim Zeitlin
parent 3217a4e8a2
commit 0e39566b3a
20 changed files with 626 additions and 133 deletions

View File

@@ -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
)

View File

@@ -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;

View File

@@ -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;
//@}

View File

@@ -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
//-----------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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` ; \

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
tests/image/toucan_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>