X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/921c65ed3d889117c600387cebb0bce2470cff8e..761598d4e5b9f59bfc773e06f843c070d920f8b9:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index cf35689226..e967b8ece9 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: image.cpp +// Name: src/common/image.cpp // Purpose: wxImage // Author: Robert Roebling // RCS-ID: $Id$ @@ -7,10 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "image.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -42,11 +38,6 @@ // For memcpy #include -#ifdef __SALFORDC__ - #undef FAR -#endif - - //----------------------------------------------------------------------------- // wxImage //----------------------------------------------------------------------------- @@ -1563,7 +1554,13 @@ bool wxImage::LoadFile( wxInputStream& stream, long type, int index ) return false; } - return handler->LoadFile(this, stream, true/*verbose*/, index); + if (!handler->CanRead(stream)) + { + wxLogError(_("Image file is not of type %d."), type); + return false; + } + else + return handler->LoadFile(this, stream, true/*verbose*/, index); } bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int index ) @@ -1581,7 +1578,13 @@ bool wxImage::LoadFile( wxInputStream& stream, const wxString& mimetype, int ind return false; } - return handler->LoadFile( this, stream, true/*verbose*/, index ); + if (!handler->CanRead(stream)) + { + wxLogError(_("Image file is not of type %s."), (const wxChar*) mimetype); + return false; + } + else + return handler->LoadFile( this, stream, true/*verbose*/, index ); } bool wxImage::SaveFile( wxOutputStream& stream, int type ) const @@ -1758,6 +1761,177 @@ wxString wxImage::GetImageExtWildcard() return wxT("(") + fmts + wxT(")|") + fmts; } +wxImage::HSVValue wxImage::RGBtoHSV(const RGBValue& rgb) +{ + const double red = rgb.red / 255.0, + green = rgb.green / 255.0, + blue = rgb.blue / 255.0; + + // find the min and max intensity (and remember which one was it for the + // latter) + double minimumRGB = red; + if ( green < minimumRGB ) + minimumRGB = green; + if ( blue < minimumRGB ) + minimumRGB = blue; + + enum { RED, GREEN, BLUE } chMax = RED; + double maximumRGB = red; + if ( green > maximumRGB ) + { + chMax = GREEN; + maximumRGB = green; + } + if ( blue > maximumRGB ) + { + chMax = BLUE; + maximumRGB = blue; + } + + const double value = maximumRGB; + + double hue = 0.0, saturation; + const double deltaRGB = maximumRGB - minimumRGB; + if ( wxIsNullDouble(deltaRGB) ) + { + // Gray has no color + hue = 0.0; + saturation = 0.0; + } + else + { + switch ( chMax ) + { + case RED: + hue = (green - blue) / deltaRGB; + break; + + case GREEN: + hue = 2.0 + (blue - red) / deltaRGB; + break; + + case BLUE: + hue = 4.0 + (red - green) / deltaRGB; + break; + + default: + wxFAIL_MSG(wxT("hue not specified")); + break; + } + + hue /= 6.0; + + if ( hue < 0.0 ) + hue += 1.0; + + saturation = deltaRGB / maximumRGB; + } + + return HSVValue(hue, saturation, value); +} + +wxImage::RGBValue wxImage::HSVtoRGB(const HSVValue& hsv) +{ + double red, green, blue; + + if ( wxIsNullDouble(hsv.saturation) ) + { + // Grey + red = hsv.value; + green = hsv.value; + blue = hsv.value; + } + else // not grey + { + 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; + + wxASSERT (angle >= -1.0 && angle <= 1.0); + count = M_IMGDATA->m_width * M_IMGDATA->m_height; + if ( count > 0 && !wxIsNullDouble(angle) ) + { + 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 //----------------------------------------------------------------------------- @@ -2017,20 +2191,20 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i wxRealPoint p3 = rotated_point (GetWidth(), 0, cos_angle, sin_angle, p0); wxRealPoint p4 = rotated_point (GetWidth(), GetHeight(), cos_angle, sin_angle, p0); - int x1 = (int) floor (wxMin (wxMin(p1.x, p2.x), wxMin(p3.x, p4.x))); - int y1 = (int) floor (wxMin (wxMin(p1.y, p2.y), wxMin(p3.y, p4.y))); - int x2 = (int) ceil (wxMax (wxMax(p1.x, p2.x), wxMax(p3.x, p4.x))); - int y2 = (int) ceil (wxMax (wxMax(p1.y, p2.y), wxMax(p3.y, p4.y))); + int x1a = (int) floor (wxMin (wxMin(p1.x, p2.x), wxMin(p3.x, p4.x))); + int y1a = (int) floor (wxMin (wxMin(p1.y, p2.y), wxMin(p3.y, p4.y))); + int x2a = (int) ceil (wxMax (wxMax(p1.x, p2.x), wxMax(p3.x, p4.x))); + int y2a = (int) ceil (wxMax (wxMax(p1.y, p2.y), wxMax(p3.y, p4.y))); // Create rotated image - wxImage rotated (x2 - x1 + 1, y2 - y1 + 1, false); + wxImage rotated (x2a - x1a + 1, y2a - y1a + 1, false); // With alpha channel if (has_alpha) rotated.SetAlpha(); if (offset_after_rotation != NULL) { - *offset_after_rotation = wxPoint (x1, y1); + *offset_after_rotation = wxPoint (x1a, y1a); } // GRG: The rotated (destination) image is always accessed @@ -2072,7 +2246,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i { for (x = 0; x < rotated.GetWidth(); x++) { - wxRealPoint src = rotated_point (x + x1, y + y1, cos_angle, -sin_angle, p0); + wxRealPoint src = rotated_point (x + x1a, y + y1a, cos_angle, -sin_angle, p0); if (-0.25 < src.x && src.x < GetWidth() - 0.75 && -0.25 < src.y && src.y < GetHeight() - 0.75) @@ -2080,8 +2254,6 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i // interpolate using the 4 enclosing grid-points. Those // points can be obtained using floor and ceiling of the // exact coordinates of the point - // C.M. 2000-02-17: when the point is near the border, special care is required. - int x1, y1, x2, y2; if (0 < src.x && src.x < GetWidth() - 1) @@ -2131,10 +2303,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i *(dst++) = *p; if (has_alpha) - { - unsigned char *p = alpha[y1] + x1; - *(alpha_dst++) = *p; - } + *(alpha_dst++) = *(alpha[y1] + x1); } else if (d2 < gs_Epsilon) { @@ -2144,10 +2313,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i *(dst++) = *p; if (has_alpha) - { - unsigned char *p = alpha[y1] + x2; - *(alpha_dst++) = *p; - } + *(alpha_dst++) = *(alpha[y1] + x2); } else if (d3 < gs_Epsilon) { @@ -2157,10 +2323,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i *(dst++) = *p; if (has_alpha) - { - unsigned char *p = alpha[y2] + x2; - *(alpha_dst++) = *p; - } + *(alpha_dst++) = *(alpha[y2] + x2); } else if (d4 < gs_Epsilon) { @@ -2170,10 +2333,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i *(dst++) = *p; if (has_alpha) - { - unsigned char *p = alpha[y2] + x1; - *(alpha_dst++) = *p; - } + *(alpha_dst++) = *(alpha[y2] + x1); } else { @@ -2202,10 +2362,10 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i if (has_alpha) { - unsigned char *v1 = alpha[y1] + (x1); - unsigned char *v2 = alpha[y1] + (x2); - unsigned char *v3 = alpha[y2] + (x2); - unsigned char *v4 = alpha[y2] + (x1); + v1 = alpha[y1] + (x1); + v2 = alpha[y1] + (x2); + v3 = alpha[y2] + (x2); + v4 = alpha[y2] + (x1); *(alpha_dst++) = (unsigned char) ( (w1 * *v1 + w2 * *v2 + @@ -2232,7 +2392,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i { for (x = 0; x < rotated.GetWidth(); x++) { - wxRealPoint src = rotated_point (x + x1, y + y1, cos_angle, -sin_angle, p0); + wxRealPoint src = rotated_point (x + x1a, y + y1a, cos_angle, -sin_angle, p0); const int xs = wxCint (src.x); // wxCint rounds to the const int ys = wxCint (src.y); // closest integer @@ -2246,10 +2406,7 @@ wxImage wxImage::Rotate(double angle, const wxPoint & centre_of_rotation, bool i *(dst++) = *p; if (has_alpha) - { - unsigned char *p = alpha[ys] + (xs); - *(alpha_dst++) = *p; - } + *(alpha_dst++) = *(alpha[ys] + (xs)); } else {