From 198c264dbcf226b5df0eed219aef30d6fdc38a71 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Thu, 24 Sep 2009 20:05:33 +0000 Subject: [PATCH] Applied part of #10034: wxImage::ConvertToDisabled() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62099 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/bitmap.h | 3 ++ include/wx/colour.h | 17 +++++- include/wx/image.h | 8 ++- interface/wx/bitmap.h | 6 +++ interface/wx/colour.h | 48 +++++++++++++++++ interface/wx/icon.h | 6 +++ interface/wx/image.h | 110 ++++++++++++++++++++++----------------- src/common/bmpbase.cpp | 10 ++++ src/common/colourcmn.cpp | 91 ++++++++++++++++++++++++++++++++ src/common/image.cpp | 50 ++++++++++++++---- 10 files changed, 288 insertions(+), 61 deletions(-) diff --git a/include/wx/bitmap.h b/include/wx/bitmap.h index e6e837d948..a287777b68 100644 --- a/include/wx/bitmap.h +++ b/include/wx/bitmap.h @@ -175,6 +175,9 @@ public: virtual wxBitmap GetSubBitmap(const wxRect& rect) const = 0; + // Convert to disabled (dimmed) bitmap. + wxBitmap ConvertToDisabled(unsigned char brightness = 255); + virtual bool SaveFile(const wxString &name, wxBitmapType type, const wxPalette *palette = NULL) const = 0; virtual bool LoadFile(const wxString &name, wxBitmapType type) = 0; diff --git a/include/wx/colour.h b/include/wx/colour.h index 6c731ef546..f2ca87a877 100644 --- a/include/wx/colour.h +++ b/include/wx/colour.h @@ -15,7 +15,6 @@ #include "wx/defs.h" #include "wx/gdiobj.h" - class WXDLLIMPEXP_FWD_CORE wxColour; // A macro to define the standard wxColour constructors: @@ -148,6 +147,22 @@ public: bool Ok() const { return IsOk(); } #endif + // manipulation + // ------------ + + // These methods are static because they are mostly used + // within tight loops (where we don't want to instantiate wxColour's) + + static void MakeMono (unsigned char* r, unsigned char* g, unsigned char* b, bool on); + static void MakeDisabled(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char brightness = 255); + static void MakeGrey (unsigned char* r, unsigned char* g, unsigned char* b); // integer version + static void MakeGrey (unsigned char* r, unsigned char* g, unsigned char* b, + double weight_r, double weight_g, double weight_b); // floating point version + static unsigned char AlphaBlend (unsigned char fg, unsigned char bg, double alpha); + static void ChangeLightness(unsigned char* r, unsigned char* g, unsigned char* b, int ialpha); + + wxColour ChangeLightness(int ialpha) const; + // old, deprecated // --------------- diff --git a/include/wx/image.h b/include/wx/image.h index eb0d19b7db..e0e05f67e2 100644 --- a/include/wx/image.h +++ b/include/wx/image.h @@ -354,13 +354,17 @@ public: unsigned char r2, unsigned char g2, unsigned char b2 ); // Convert to greyscale image. Uses the luminance component (Y) of the image. - // The luma value (YUV) is calculated using (R * lr) + (G * lg) + (B * lb), defaults to ITU-T BT.601 - wxImage ConvertToGreyscale( double lr = 0.299, double lg = 0.587, double lb = 0.114 ) const; + // The luma value (YUV) is calculated using (R * weight_r) + (G * weight_g) + (B * weight_b), defaults to ITU-T BT.601 + wxImage ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const; + wxImage ConvertToGreyscale(void) const; // convert to monochrome image ( will be replaced by white, // everything else by black) wxImage ConvertToMono( unsigned char r, unsigned char g, unsigned char b ) const; + // Convert to disabled (dimmed) image. + wxImage ConvertToDisabled(unsigned char brightness = 255) 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 ); diff --git a/interface/wx/bitmap.h b/interface/wx/bitmap.h index 1d2b8b81f8..913d530e9e 100644 --- a/interface/wx/bitmap.h +++ b/interface/wx/bitmap.h @@ -498,6 +498,12 @@ public: */ wxSize GetSize() const; + /** + Returns disabled (dimmed) version of the bitmap. + @since 2.9.0 + */ + wxBitmap ConvertToDisabled(unsigned char brightness = 255) const; + /** Gets the width of the bitmap in pixels. diff --git a/interface/wx/colour.h b/interface/wx/colour.h index d6f3fa5f82..82134dd1fb 100644 --- a/interface/wx/colour.h +++ b/interface/wx/colour.h @@ -213,6 +213,54 @@ public: colours and alpha values. */ bool operator ==(const wxColour& colour) const; + + /** + Assign 0 or 255 to rgb out parameters. + @since 2.9.0 + */ + static void MakeMono(unsigned char* r, unsigned char* g, unsigned char* b, bool on); + + /** + Create a disabled (dimmed) colour from (in/out) rgb parameters. + @since 2.9.0 + */ + static void MakeDisabled(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char brightness = 255); + + /** + Create a grey colour from (in/out) rgb parameters using integer arithmetic. + @since 2.9.0 + */ + static void MakeGrey(unsigned char* r, unsigned char* g, unsigned char* b); + + /** + Create a grey colour from (in/out) rgb parameters using floating point arithmetic. + 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). + @since 2.9.0 + */ + static void MakeGrey(unsigned char* r, unsigned char* g, unsigned char* b, + double weight_r, double weight_g, double weight_b); + + /** + Blend colour, taking alpha into account. + @since 2.9.0 + */ + static unsigned char AlphaBlend(unsigned char fg, unsigned char bg, double alpha); + + /** + ChangeLightness() is a utility function that simply darkens + or lightens a color, based on the specified percentage + ialpha of 0 would be completely black, 200 completely white + an ialpha of 100 returns the same colour + @since 2.9.0 + */ + static void ChangeLightness(unsigned char* r, unsigned char* g, unsigned char* b, int ialpha); + + /** + wxColour wrapper for ChangeLightness(r,g,b,ialpha). + @since 2.9.0 + */ + wxColour ChangeLightness(int ialpha) const; }; diff --git a/interface/wx/icon.h b/interface/wx/icon.h index 5a055a7168..9cb95d7348 100644 --- a/interface/wx/icon.h +++ b/interface/wx/icon.h @@ -171,6 +171,12 @@ public: */ virtual ~wxIcon(); + /** + Returns disabled (dimmed) version of the icon. MSW only. + @since 2.9.0 + */ + wxIcon ConvertToDisabled(unsigned char brightness = 255) const; + /** Copies @a bmp bitmap to this icon. Under MS Windows the bitmap must have mask colour set. diff --git a/interface/wx/image.h b/interface/wx/image.h index 1b44387d2a..43dcf59028 100644 --- a/interface/wx/image.h +++ b/interface/wx/image.h @@ -109,23 +109,23 @@ public: /** Returns @true if this handler supports the image format contained in the given stream. - + This function doesn't modify the current stream position (because it restores the original position before returning; this however requires the stream to be seekable; see wxStreamBase::IsSeekable). */ - bool CanRead( wxInputStream& stream ); + bool CanRead( wxInputStream& stream ); /** Returns @true if this handler supports the image format contained in the file with the given name. - + This function doesn't modify the current stream position (because it restores the original position before returning; this however requires the stream to be seekable; see wxStreamBase::IsSeekable). */ bool CanRead( const wxString& filename ); - + /** Gets the preferred file extension associated with this handler. @@ -348,7 +348,7 @@ class wxImage : public wxObject { public: /** - A simple class which stores red, green and blue values as 8 bit unsigned integers + A simple class which stores red, green and blue values as 8 bit unsigned integers in the range of 0-255. */ class RGBValue @@ -398,7 +398,7 @@ public: If @true, initialize the image to black. */ wxImage(int width, int height, bool clear = true); - + /** @overload */ @@ -425,7 +425,7 @@ public: @overload */ wxImage(const wxSize& sz, unsigned char* data, bool static_data = false); - + /** Creates an image from data in memory. If @a static_data is @false then the wxImage will take ownership of the data and free it @@ -451,7 +451,7 @@ public: */ wxImage(const wxSize& sz, unsigned char* data, unsigned char* data, unsigned char* alpha, bool static_data = false); - + /** Creates an image from XPM data. @@ -549,13 +549,13 @@ public: */ virtual ~wxImage(); - - + + /** @name Image creation, initialization and deletion functions */ //@{ - + /** Returns an identical copy of this image. */ @@ -577,7 +577,7 @@ public: /** Creates a fresh image. See wxImage::wxImage(int,int,unsigned char*,bool) for more info. - + @return @true if the call succeeded, @false otherwise. */ bool Create( int width, int height, unsigned char* data, bool static_data = false ); @@ -590,16 +590,16 @@ public: /** Creates a fresh image. See wxImage::wxImage(int,int,unsigned char*,unsigned char*,bool) for more info. - + @return @true if the call succeeded, @false otherwise. */ bool Create( int width, int height, unsigned char* data, unsigned char* alpha, bool static_data = false ); - + /** @overload */ bool Create( const wxSize& sz, unsigned char* data, unsigned char* alpha, bool static_data = false ); - + /** Initialize the image data with zeroes (the default) or with the byte value given as @a value. @@ -612,7 +612,7 @@ public: Destroys the image data. */ void Destroy(); - + /** Initializes the image alpha channel data. @@ -773,7 +773,7 @@ public: */ wxImage Scale(int width, int height, wxImageResizeQuality quality = wxIMAGE_QUALITY_NORMAL) const; - + /** Returns a resized version of this image without scaling it by adding either a border with the given colour or cropping as necessary. @@ -847,9 +847,15 @@ public: The returned image uses the luminance component of the original to calculate the greyscale. Defaults to using the standard ITU-T BT.601 when converting to YUV, where every pixel equals - (R * @a lr) + (G * @a lg) + (B * @a lb). + (R * @a weight_r) + (G * @a weight_g) + (B * @a weight_b). + */ + wxImage ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const; + + /** + Returns a greyscale version of the image. + @since 2.9.0 */ - wxImage ConvertToGreyscale(double lr = 0.299, double lg = 0.587, double lb = 1.114) const; + wxImage ConvertToGreyscale() const; /** Returns monochromatic version of the image. @@ -858,15 +864,21 @@ public: colour and black colour everywhere else. */ wxImage ConvertToMono(unsigned char r, unsigned char g, unsigned char b) const; - + + /** + Returns disabled (dimmed) version of the image. + @since 2.9.0 + */ + wxImage ConvertToDisabled(unsigned char brightness = 255) const; + //@} - - + + /** @name Miscellaneous functions */ //@{ - + /** Computes the histogram of the image. @a histogram is a reference to wxImageHistogram object. wxImageHistogram is a specialization of @@ -889,7 +901,7 @@ public: @return Returns number of colours in the histogram. */ unsigned long ComputeHistogram(wxImageHistogram& histogram) const; - + /** Finds the first colour that is never used in the image. The search begins at given initial colour and continues by increasing @@ -922,10 +934,10 @@ public: @return Returns 'this' object. */ wxImage& operator=(const wxImage& image); - + //@} - - + + /** @name Getters */ @@ -1011,7 +1023,7 @@ public: @see GetHeight(), GetWidth() */ wxSize GetSize() const; - + /** Gets a user-defined string-valued option. @@ -1390,12 +1402,12 @@ public: The data must have been allocated with @c malloc(), @b NOT with @c operator new. - If @a static_data is @false, after this call the pointer to the data is + If @a static_data is @false, after this call the pointer to the data is owned by the wxImage object, that will be responsible for deleting it. Do not pass to this function a pointer obtained through GetData(). */ void SetData(unsigned char* data, bool static_data = false); - + /** @overload */ @@ -1453,8 +1465,8 @@ public: @see GetOption(), GetOptionInt(), HasOption() */ void SetOption(const wxString& name, const wxString& value); - - /** + + /** @overload */ void SetOption(const wxString& name, int value); @@ -1498,14 +1510,14 @@ public: void SetType(wxBitmapType type); //@} - - - + + + /** @name Handler management functions */ //@{ - + /** Register an image handler. See @ref image_handlers for a list of the available handlers. @@ -1517,7 +1529,7 @@ public: This function is called by wxWidgets on exit. */ static void CleanUpHandlers(); - + /** Finds the handler with the given name. @@ -1610,22 +1622,22 @@ public: @see wxImageHandler */ static bool RemoveHandler(const wxString& name); - + //@} - - + + /** - Returns @true if at least one of the available image handlers can read + Returns @true if at least one of the available image handlers can read the file with the given name. - + See wxImageHandler::CanRead for more info. */ static bool CanRead(const wxString& filename); - + /** - Returns @true if at least one of the available image handlers can read + Returns @true if at least one of the available image handlers can read the data in the given stream. - + See wxImageHandler::CanRead for more info. */ static bool CanRead(wxInputStream& stream); @@ -1640,7 +1652,7 @@ public: of the file to query. For the overload taking the parameter @a stream, that's the opened input stream with image data. - + See wxImageHandler::GetImageCount() for more info. The parameter @a type may be one of the following values: @@ -1686,12 +1698,12 @@ public: @see wxImageHandler */ static wxString GetImageExtWildcard(); - + /** Converts a color in RGB color space to HSV color space. */ static wxImage::HSVValue RGBtoHSV(const wxImage::RGBValue& rgb); - + /** Converts a color in HSV color space to RGB color space. */ @@ -1714,7 +1726,7 @@ wxImage wxNullImage; /** Initializes all available image handlers. For a list of available handlers, see wxImage. - If you don't need/want all image handlers loaded + If you don't need/want all image handlers loaded @see wxImage, wxImageHandler diff --git a/src/common/bmpbase.cpp b/src/common/bmpbase.cpp index e80091dada..eebf56e5f9 100644 --- a/src/common/bmpbase.cpp +++ b/src/common/bmpbase.cpp @@ -135,6 +135,16 @@ public: void OnExit() { wxBitmap::CleanUpHandlers(); } }; +wxBitmap wxBitmapBase::ConvertToDisabled(unsigned char brightness) const +{ + wxBitmap bmp; +#if wxUSE_IMAGE + wxImage image = ConvertToImage(); + bmp = wxBitmap(image.ConvertToDisabled(brightness)); +#endif + return bmp; +} + IMPLEMENT_DYNAMIC_CLASS(wxBitmapBaseModule, wxModule) #endif // wxUSE_BITMAP_BASE diff --git a/src/common/colourcmn.cpp b/src/common/colourcmn.cpp index 8fa9c927c2..943ceb5683 100644 --- a/src/common/colourcmn.cpp +++ b/src/common/colourcmn.cpp @@ -149,6 +149,97 @@ wxString wxColourBase::GetAsString(long flags) const return colName; } +// static +void wxColourBase::MakeMono(unsigned char* r, unsigned char* g, unsigned char* b, + bool on) +{ + *r = *g = *b = on ? 255 : 0; +} + +// static +void wxColourBase::MakeGrey(unsigned char* r, unsigned char* g, unsigned char* b + /*, unsigned char brightness */ + ) +{ + *r = *g = *b = (wxByte)(((*b)*117UL + (*g)*601UL + (*r)*306UL) >> 10); +} + +// static +void wxColourBase::MakeGrey(unsigned char* r, unsigned char* g, unsigned char* b, + double weight_r, double weight_g, double weight_b) +{ + double luma = (*r) * weight_r + (*g) * weight_g + (*b) * weight_b; + *r = *g = *b = (wxByte)wxRound(luma); +} + +// static +void wxColourBase::MakeDisabled(unsigned char* r, unsigned char* g, unsigned char* b, + unsigned char brightness) +{ + //MakeGrey(r, g, b, brightness); // grey no-blend version + *r = AlphaBlend(*r, brightness, 0.4); + *g = AlphaBlend(*g, brightness, 0.4); + *b = AlphaBlend(*b, brightness, 0.4); +} + +// AlphaBlend is used by ChangeLightness and MakeDisabled + +// static +unsigned char wxColourBase::AlphaBlend(unsigned char fg, unsigned char bg, + double alpha) +{ + double result = bg + (alpha * (fg - bg)); + result = wxMax(result, 0.0); + result = wxMin(result, 255.0); + return (unsigned char)result; +} + +// ChangeLightness() is a utility function that simply darkens +// or lightens a color, based on the specified percentage +// ialpha of 0 would be completely black, 100 completely white +// an ialpha of 100 returns the same colour + +// static +void wxColourBase::ChangeLightness(unsigned char* r, unsigned char* g, unsigned char* b, + int ialpha) +{ + if (ialpha == 100) return; + + // ialpha is 0..200 where 0 is completely black + // and 200 is completely white and 100 is the same + // convert that to normal alpha 0.0 - 1.0 + ialpha = wxMax(ialpha, 0); + ialpha = wxMin(ialpha, 200); + double alpha = ((double)(ialpha - 100.0))/100.0; + + unsigned char bg; + if (ialpha > 100) + { + // blend with white + bg = 255; + alpha = 1.0 - alpha; // 0 = transparent fg; 1 = opaque fg + } + else + { + // blend with black + bg = 0; + alpha = 1.0 + alpha; // 0 = transparent fg; 1 = opaque fg + } + + *r = AlphaBlend(*r, bg, alpha); + *g = AlphaBlend(*g, bg, alpha); + *b = AlphaBlend(*b, bg, alpha); +} + +wxColour wxColourBase::ChangeLightness(int ialpha) const +{ + wxByte r = Red(); + wxByte g = Green(); + wxByte b = Blue(); + ChangeLightness(&r, &g, &b, ialpha); + return wxColour(r,g,b); +} + #if WXWIN_COMPATIBILITY_2_6 // static diff --git a/src/common/image.cpp b/src/common/image.cpp index e13640c4d6..a3c9483767 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -26,6 +26,7 @@ #include "wx/module.h" #include "wx/palette.h" #include "wx/intl.h" + #include "wx/colour.h" #endif #include "wx/filefn.h" @@ -1436,7 +1437,12 @@ void wxImage::Replace( unsigned char r1, unsigned char g1, unsigned char b1, } } -wxImage wxImage::ConvertToGreyscale( double lr, double lg, double lb ) const +wxImage wxImage::ConvertToGreyscale(void) const +{ + return ConvertToGreyscale(0.299, 0.587, 0.114); +} + +wxImage wxImage::ConvertToGreyscale(double weight_r, double weight_g, double weight_b) const { wxImage image; @@ -1460,16 +1466,14 @@ wxImage wxImage::ConvertToGreyscale( double lr, double lg, double lb ) const const long size = M_IMGDATA->m_width * M_IMGDATA->m_height; for ( long i = 0; i < size; i++, src += 3, dest += 3 ) { + memcpy(dest, src, 3); // don't modify the mask if ( hasMask && src[0] == maskRed && src[1] == maskGreen && src[2] == maskBlue ) { - memcpy(dest, src, 3); } else { - // calculate the luma - double luma = (src[0] * lr + src[1] * lg + src[2] * lb) + 0.5; - dest[0] = dest[1] = dest[2] = static_cast(luma); + wxColour::MakeGrey(dest + 0, dest + 1, dest + 2, weight_r, weight_g, weight_b); } } @@ -1514,15 +1518,43 @@ wxImage wxImage::ConvertToMono( unsigned char r, unsigned char g, unsigned char for ( long i = 0; i < size; i++, srcd += 3, tard += 3 ) { - if (srcd[0] == r && srcd[1] == g && srcd[2] == b) - tard[0] = tard[1] = tard[2] = 255; - else - tard[0] = tard[1] = tard[2] = 0; + bool on = (srcd[0] == r) && (srcd[1] == g) && (srcd[2] == b); + wxColourBase::MakeMono(tard + 0, tard + 1, tard + 2, on); } return image; } +wxImage wxImage::ConvertToDisabled(unsigned char brightness) const +{ + wxImage image = *this; + + unsigned char mr = image.GetMaskRed(); + unsigned char mg = image.GetMaskGreen(); + unsigned char mb = image.GetMaskBlue(); + + int width = image.GetWidth(); + int height = image.GetHeight(); + bool has_mask = image.HasMask(); + + for (int y = height-1; y >= 0; --y) + { + for (int x = width-1; x >= 0; --x) + { + unsigned char* data = image.GetData() + (y*(width*3))+(x*3); + unsigned char* r = data; + unsigned char* g = data+1; + unsigned char* b = data+2; + + if (has_mask && (*r == mr) && (*g == mg) && (*b == mb)) + continue; + + wxColour::MakeDisabled(r, g, b, brightness); + } + } + return image; +} + int wxImage::GetWidth() const { wxCHECK_MSG( Ok(), 0, wxT("invalid image") ); -- 2.45.2