- Fixed wxScopeGuard to work with VC++, documented it.
- Fixed proxy handling in wxURL.
- Added wxZipFSHandler::Cleanup() (Stas Sergeev)
+- Added wxImage::RotateHue() and RGB <-> HSV conversions (John Anderson)
All (GUI):
\helpref{wxImage::GetHeight}{wximagegetheight}
+\membersection{HSVValue::HSVValue}\label{hsvvaluehsvvalue}
+
+\func{}{HSVValue}{\param{double }{h = 0.0}, \param{double }{s = 0.0}, \param{double }{v = 0.0}}
+
+Constructor for HSVValue, an object that contains values for hue, saturation and value which
+represent the value of a color. It is used by \helpref{wxImage::HSVtoRGB}{wximagehsvtorgb}
+and \helpref{wxImage::RGBtoHSV}{wximagergbtohsv}, which
+converts between HSV color space and RGB color space.
+
+\pythonnote{use wxImage\_HSVValue in wxPython}
+
+
+
+\membersection{wxImage::HSVtoRGB}\label{wximagehsvtorgb}
+
+\func{wxImage::RGBValue}{HSVtoRGB}{\param{const HSVValue \& }{hsv}}
+
+Converts a color in HSV color space to RGB color space.
+
+
\membersection{wxImage::HasAlpha}\label{wximagehasalpha}
\constfunc{bool}{HasAlpha}{\void}
Returns true if image data is present.
+\membersection{RGBValue::RGBValue}\label{rgbvaluergbvalue}
+
+\func{}{RGBValue}{\param{unsigned char }{r = 0}, \param{unsigned char }{g = 0}, \param{unsigned char }{b = 0}}
+
+Constructor for RGBValue, an object that contains values for red, green and blud which
+represent the value of a color. It is used by \helpref{wxImage::HSVtoRGB}{wximagehsvtorgb}
+and \helpref{wxImage::RGBtoHSV}{wximagergbtohsv}, which
+converts between HSV color space and RGB color space.
+
+\pythonnote{use wxImage\_RGBValue in wxPython}
+
+
+\membersection{wxImage::RGBtoHSV}\label{wximagergbtohsv}
+
+\func{wxImage::HSVValue}{RGBtoHSV}{\param{const RGBValue\& }{rgb}}
+
+Converts a color in RGB color space to HSV color space.
+
+
\membersection{wxImage::RemoveHandler}\label{wximageremovehandler}
\func{static bool}{RemoveHandler}{\param{const wxString\& }{name}}
Returns the rotated image, leaving this image intact.
+\membersection{wxImage::RotateHue}\label{wximagerotatehue}
+
+\func{void}{RotateHue}{\param{double}{ angle}}
+
+Rotates the hue of each pixel in the image by {\it angle}, which is a double in
+the range of -1.0 to +1.0, where -1.0 corresponds to -360 degrees and +1.0 corresponds
+to +360 degrees.
+
+
\membersection{wxImage::Rotate90}\label{wximagerotate90}
\constfunc{wxImage}{Rotate90}{\param{bool}{ clockwise = true}}
class WXDLLEXPORT wxImage: public wxObject
{
public:
+#if wxABI_VERSION >= 20602
+ // red, green and blue are 8 bit unsigned integers in the range of 0..255
+ // We use the identifier RGBValue instead of RGB, since RGB is #defined
+ class RGBValue
+ {
+ public:
+ RGBValue(unsigned char r=0, unsigned char g=0, unsigned char b=0)
+ : red(r), green(g), blue(b) {}
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ };
+
+ // hue, saturation and value are doubles in the range 0.0..1.0
+ class HSVValue
+ {
+ public:
+ HSVValue(double h=0.0, double s=0.0, double v=0.0)
+ : hue(h), saturation(s), value(v) {}
+ double hue;
+ double saturation;
+ double value;
+ };
+#endif // wxABI_VERSION >= 2.6.2
+
wxImage(){}
wxImage( int width, int height, bool clear = true );
wxImage( int width, int height, unsigned char* data, bool static_data = false );
// Returned value: # of entries in the histogram
unsigned long ComputeHistogram( wxImageHistogram &h ) const;
+#if wxABI_VERSION >= 20602
+ // 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
+ void RotateHue(double angle);
+#endif // wxABI_VERSION >= 2.6.2
+
wxImage& operator = (const wxImage& image)
{
if ( (*this) != image )
static void CleanUpHandlers();
static void InitStandardHandlers();
+#if wxABI_VERSION >= 20602
+ static HSVValue RGBtoHSV(const RGBValue& rgb);
+ static RGBValue HSVtoRGB(const HSVValue& hsv);
+#endif // wxABI_VERSION >= 2.6.2
+
+
protected:
static wxList sm_handlers;
wxBitmap *my_horse_asciigrey_pnm;
wxBitmap *my_horse_rawgrey_pnm;
+ wxBitmap *colorized_horse_jpeg;
+
int xH, yH ;
int m_ani_images ;
my_horse_ico = (wxBitmap*) NULL;
my_horse_cur = (wxBitmap*) NULL;
my_horse_ani = (wxBitmap*) NULL;
+ colorized_horse_jpeg = (wxBitmap*) NULL;
my_smile_xbm = (wxBitmap*) NULL;
my_square = (wxBitmap*) NULL;
if ( !image.LoadFile( dir + _T("horse.jpg")) )
wxLogError(wxT("Can't load JPG image"));
else
+ {
my_horse_jpeg = new wxBitmap( image );
+ // Colorize by rotating green hue to red
+ wxImage::HSVValue greenHSV = wxImage::RGBtoHSV(wxImage::RGBValue(0, 255, 0));
+ wxImage::HSVValue redHSV = wxImage::RGBtoHSV(wxImage::RGBValue(255, 0, 0));
+ image.RotateHue(redHSV.hue - greenHSV.hue);
+ colorized_horse_jpeg = new wxBitmap( image );
+ }
#endif // wxUSE_LIBJPEG
#if wxUSE_GIF
delete my_anti;
delete my_horse_asciigrey_pnm;
delete my_horse_rawgrey_pnm;
+ delete colorized_horse_jpeg;
}
void MyCanvas::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
dc.DrawBitmap( my_horse_ani[i], 230 + i * 2 * my_horse_ani[i].GetWidth() , 2420, true );
}
+#if wxUSE_LIBJPEG
+ if (colorized_horse_jpeg)
+ {
+ dc.DrawText( _T("Colorize image by rotating green hue to red"), 30, 2490 );
+ dc.DrawBitmap( *colorized_horse_jpeg, 30, 2520 );
+ }
+#endif // wxUSE_LIBJPEG
+
}
void MyCanvas::CreateAntiAliasedBitmap()
m_canvas = new MyCanvas( this, wxID_ANY, wxPoint(0,0), wxSize(10,10) );
- // 500 width * 2500 height
- m_canvas->SetScrollbars( 10, 10, 50, 250 );
+ // 500 width * 2750 height
+ m_canvas->SetScrollbars( 10, 10, 50, 275 );
}
void MyFrame::OnQuit( wxCommandEvent &WXUNUSED(event) )
// For memcpy
#include <string.h>
-#ifdef __SALFORDC__
- #undef FAR
-#endif
-
-
//-----------------------------------------------------------------------------
// wxImage
//-----------------------------------------------------------------------------
return wxT("(") + fmts + wxT(")|") + fmts;
}
+wxImage::HSVValue wxImage::RGBtoHSV(const RGBValue& rgb)
+{
+ double hue, saturation, value;
+
+ const double red = rgb.red / 255.0,
+ green = rgb.green / 255.0,
+ blue = rgb.blue / 255.0;
+
+ double minimumRGB = red;
+ if (green < minimumRGB)
+ minimumRGB = green;
+
+ if (blue < minimumRGB)
+ minimumRGB = blue;
+
+ double maximumRGB = red;
+ if (green > maximumRGB)
+ maximumRGB = green;
+
+ if (blue > maximumRGB)
+ maximumRGB = blue;
+
+ value = maximumRGB;
+
+ if (maximumRGB == minimumRGB)
+ {
+ // Gray has no color
+ hue = 0.0;
+ saturation = 0.0;
+ }
+ else
+ {
+ double deltaRGB = maximumRGB - minimumRGB;
+
+ saturation = deltaRGB / maximumRGB;
+
+ if ( red == maximumRGB )
+ hue = (green - blue) / deltaRGB;
+ else if (green == maximumRGB)
+ hue = 2.0 + (blue - red) / deltaRGB;
+ else
+ hue = 4.0 + (red - green) / deltaRGB;
+
+ hue = hue / 6.0;
+
+ if (hue < 0.0)
+ hue = hue + 1.0;
+ }
+
+ return HSVValue(hue, saturation, value);
+}
+
+wxImage::RGBValue wxImage::HSVtoRGB(const HSVValue& hsv)
+{
+ double red, green, blue;
+
+ if ( hsv.saturation == 0.0 )
+ {
+ red = hsv.value; //Grey
+ green = hsv.value;
+ blue = hsv.value;
+ }
+ else
+ {
+ double hue = hsv.hue * 6.0; // sector 0 to 5
+ int i = (int)floor(hue);
+ double f = hue - i; // fractional part of h
+ double p = hsv.value * (1.0 - hsv.saturation);
+
+ switch (i)
+ {
+ case 0:
+ red = hsv.value;
+ green = hsv.value * (1.0 - hsv.saturation * (1.0 - f));
+ blue = p;
+ break;
+
+ case 1:
+ red = hsv.value * (1.0 - hsv.saturation * f);
+ green = hsv.value;
+ blue = p;
+ break;
+
+ case 2:
+ red = p;
+ green = hsv.value;
+ blue = hsv.value * (1.0 - hsv.saturation * (1.0 - f));
+ break;
+
+ case 3:
+ red = p;
+ green = hsv.value * (1.0 - hsv.saturation * f);
+ blue = hsv.value;
+ break;
+
+ case 4:
+ red = hsv.value * (1.0 - hsv.saturation * (1.0 - f));
+ green = p;
+ blue = hsv.value;
+ break;
+
+ default: // case 5:
+ red = hsv.value;
+ green = p;
+ blue = hsv.value * (1.0 - hsv.saturation * f);
+ break;
+ }
+ }
+
+ return RGBValue((unsigned char)(red * 255.0),
+ (unsigned char)(green * 255.0),
+ (unsigned char)(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
+ */
+void wxImage::RotateHue(double angle)
+{
+ unsigned char *srcBytePtr;
+ unsigned char *dstBytePtr;
+ unsigned long count;
+ wxImage::HSVValue hsv;
+ wxImage::RGBValue rgb;
+
+ assert (angle >= -1.0 && angle <= 1.0);
+ count = M_IMGDATA->m_width * M_IMGDATA->m_height;
+ if (count > 0 && angle != 0.0)
+ {
+ srcBytePtr = M_IMGDATA->m_data;
+ dstBytePtr = srcBytePtr;
+ do
+ {
+ rgb.red = *srcBytePtr++;
+ rgb.green = *srcBytePtr++;
+ rgb.blue = *srcBytePtr++;
+ hsv = RGBtoHSV(rgb);
+
+ 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;
+
+ rgb = HSVtoRGB(hsv);
+ *dstBytePtr++ = rgb.red;
+ *dstBytePtr++ = rgb.green;
+ *dstBytePtr++ = rgb.blue;
+ } while (--count != 0);
+ }
+}
+
//-----------------------------------------------------------------------------
// wxImageHandler
//-----------------------------------------------------------------------------
*wxLogBuffer*;
*wxGenericListCtrl*SetItemFont*wxFont*;
*wxGenericListCtrl*GetItemFont*;
+ *wxImage*HSVValue*;
+ *wxImage*RGBValue*;
+ *wxImage*RotateHue*;
*wxMessageOutputBest*;
*wxShadowObject*;
*wxWizard*FinishLayout*;
%rename(IMAGE_ALPHA_OPAQUE) wxIMAGE_ALPHA_OPAQUE;
%rename(ImageHandler) wxImageHandler;
%rename(ImageHistogram) wxImageHistogram;
+%rename(Image_RGBValue) wxImage_RGBValue;
+%rename(Image_HSVValue) wxImage_HSVValue;
%rename(Image) wxImage;
%rename(NullImage) wxNullImage;
%rename(IMAGE_RESOLUTION_INCHES) wxIMAGE_RESOLUTION_INCHES;
with `HasAlpha`. Note that currently only images loaded from PNG files
with transparency information will have an alpha channel.", "");
+%{
+// Pull the nested class out to the top level for SWIG's sake
+#define wxImage_RGBValue wxImage::RGBValue
+#define wxImage_HSVValue wxImage::HSVValue
+%}
+
+class wxImage_RGBValue
+{
+public:
+ wxImage_RGBValue(byte r=0, byte g=0, byte b=0);
+ byte red;
+ byte green;
+ byte blue;
+};
+
+class wxImage_HSVValue
+{
+public:
+ wxImage_HSVValue(double h=0.0, double s=0.0, double v=0.0);
+ double hue;
+ double saturation;
+ double value;
+};
+
+
class wxImage : public wxObject {
public:
%typemap(out) wxImage*; // turn off this typemap
}
}
+
+ DocDeclStr(
+ void , RotateHue(double angle),
+ "Rotates the hue of each pixel of the image. Hue is a double in the
+range -1.0..1.0 where -1.0 is -360 degrees and 1.0 is 360 degrees", "");
+
+ static wxImage_HSVValue RGBtoHSV(wxImage_RGBValue rgb);
+ static wxImage_RGBValue HSVtoRGB(wxImage_HSVValue hsv);
+
%pythoncode { def __nonzero__(self): return self.Ok() }
};