diff --git a/build/cmake/tests/gui/CMakeLists.txt b/build/cmake/tests/gui/CMakeLists.txt index a28a975998..0333a85731 100644 --- a/build/cmake/tests/gui/CMakeLists.txt +++ b/build/cmake/tests/gui/CMakeLists.txt @@ -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 ) diff --git a/include/wx/image.h b/include/wx/image.h index 125b8c707d..8831d675c2 100644 --- a/include/wx/image.h +++ b/include/wx/image.h @@ -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 + void ApplyToAllPixels(void (*filter)(wxImage *, unsigned char *, T), T value); + private: friend class WXDLLIMPEXP_FWD_CORE wxImageHandler; diff --git a/interface/wx/image.h b/interface/wx/image.h index 2bf152168c..ff6baefdb5 100644 --- a/interface/wx/image.h +++ b/interface/wx/image.h @@ -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; + //@} diff --git a/samples/image/image.cpp b/samples/image/image.cpp index 4ecbf16203..ec3b894310 100644 --- a/samples/image/image.cpp +++ b/samples/image/image.cpp @@ -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(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 //----------------------------------------------------------------------------- diff --git a/src/common/image.cpp b/src/common/image.cpp index 78fe5b82a3..7f234f4564 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -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 +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 diff --git a/tests/Makefile.in b/tests/Makefile.in index 48bebb8a78..07decd53f6 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -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` ; \ diff --git a/tests/image/image.cpp b/tests/image/image.cpp index af70bc21ee..d75ee42caa 100644 --- a/tests/image/image.cpp +++ b/tests/image/image.cpp @@ -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 */ diff --git a/tests/image/toucan.png b/tests/image/toucan.png new file mode 100644 index 0000000000..03960d4939 Binary files /dev/null and b/tests/image/toucan.png differ diff --git a/tests/image/toucan_bright_-0.259.png b/tests/image/toucan_bright_-0.259.png new file mode 100644 index 0000000000..b415a36af0 Binary files /dev/null and b/tests/image/toucan_bright_-0.259.png differ diff --git a/tests/image/toucan_dis_240.png b/tests/image/toucan_dis_240.png new file mode 100644 index 0000000000..66e0d8db49 Binary files /dev/null and b/tests/image/toucan_dis_240.png differ diff --git a/tests/image/toucan_grey.png b/tests/image/toucan_grey.png new file mode 100644 index 0000000000..e25e9090a8 Binary files /dev/null and b/tests/image/toucan_grey.png differ diff --git a/tests/image/toucan_hsv_0.538_-0.41_-0.259.png b/tests/image/toucan_hsv_0.538_-0.41_-0.259.png new file mode 100644 index 0000000000..ecd29cce11 Binary files /dev/null and b/tests/image/toucan_hsv_0.538_-0.41_-0.259.png differ diff --git a/tests/image/toucan_hue_0.538.png b/tests/image/toucan_hue_0.538.png new file mode 100644 index 0000000000..2a559d3bd4 Binary files /dev/null and b/tests/image/toucan_hue_0.538.png differ diff --git a/tests/image/toucan_light_46.png b/tests/image/toucan_light_46.png new file mode 100644 index 0000000000..7eba6c5938 Binary files /dev/null and b/tests/image/toucan_light_46.png differ diff --git a/tests/image/toucan_mono_255_255_255.png b/tests/image/toucan_mono_255_255_255.png new file mode 100644 index 0000000000..9dc3078958 Binary files /dev/null and b/tests/image/toucan_mono_255_255_255.png differ diff --git a/tests/image/toucan_sat_-0.41.png b/tests/image/toucan_sat_-0.41.png new file mode 100644 index 0000000000..8c89c7c065 Binary files /dev/null and b/tests/image/toucan_sat_-0.41.png differ diff --git a/tests/makefile.bcc b/tests/makefile.bcc index ef3b570077..060b96dbf2 100644 --- a/tests/makefile.bcc +++ b/tests/makefile.bcc @@ -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 diff --git a/tests/makefile.gcc b/tests/makefile.gcc index 41533554eb..99f099a87b 100644 --- a/tests/makefile.gcc +++ b/tests/makefile.gcc @@ -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 diff --git a/tests/makefile.vc b/tests/makefile.vc index d7ba6a6280..836677b107 100644 --- a/tests/makefile.vc +++ b/tests/makefile.vc @@ -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 diff --git a/tests/test.bkl b/tests/test.bkl index df402f68dc..d4b7e2d829 100644 --- a/tests/test.bkl +++ b/tests/test.bkl @@ -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