]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/image.cpp
Implement support for gradient stops for OS X.
[wxWidgets.git] / src / common / image.cpp
index 1c527ca0d7ba891a99029acf74d50bfb9595a087..6dddaefb3c764b236070e6d788f0981adf790106 100644 (file)
@@ -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"
@@ -616,8 +617,11 @@ wxImage wxImage::ResampleBilinear(int width, int height) const
 
     double srcpixy, srcpixy1, srcpixy2, dy, dy1;
     double srcpixx, srcpixx1, srcpixx2, dx, dx1;
-    double r1, g1, b1, a1;
-    double r2, g2, b2, a2;
+
+    // initialize alpha values to avoid g++ warnings about possibly
+    // uninitialized variables
+    double r1, g1, b1, a1 = 0;
+    double r2, g2, b2, a2 = 0;
 
     for ( int dsty = 0; dsty < height; dsty++ )
     {
@@ -664,13 +668,13 @@ wxImage wxImage::ResampleBilinear(int width, int height) const
 
             //result lines
 
-            dst_data[0] = r1 * dy1 + r2 * dy;
-            dst_data[1] = g1 * dy1 + g2 * dy;
-            dst_data[2] = b1 * dy1 + b2 * dy;
+            dst_data[0] = static_cast<unsigned char>(r1 * dy1 + r2 * dy);
+            dst_data[1] = static_cast<unsigned char>(g1 * dy1 + g2 * dy);
+            dst_data[2] = static_cast<unsigned char>(b1 * dy1 + b2 * dy);
             dst_data += 3;
 
             if ( src_alpha )
-                *dst_alpha++ = a1 * dy1 + a2 * dy;
+                *dst_alpha++ = static_cast<unsigned char>(a1 * dy1 + a2 * dy);
         }
     }
 
@@ -1279,21 +1283,30 @@ wxImage wxImage::Size( const wxSize& size, const wxPoint& pos,
 
     image.SetRGB(wxRect(), r, g, b);
 
-    wxRect subRect(pos.x, pos.y, width, height);
-    wxRect finalRect(0, 0, size.GetWidth(), size.GetHeight());
-    if (pos.x < 0)
-        finalRect.width -= pos.x;
-    if (pos.y < 0)
-        finalRect.height -= pos.y;
+    // we have two coordinate systems:
+    // source:     starting at 0,0 of source image
+    // destination starting at 0,0 of destination image
+    // Documentation says:
+    // "The image is pasted into a new image [...] at the position pos relative
+    // to the upper left of the new image." this means the transition rule is:
+    // "dest coord" = "source coord" + pos;
+
+    // calculate the intersection using source coordinates:
+    wxRect srcRect(0, 0, width, height);
+    wxRect dstRect(-pos, size);
 
-    subRect.Intersect(finalRect);
+    srcRect.Intersect(dstRect);
 
-    if (!subRect.IsEmpty())
+    if (!srcRect.IsEmpty())
     {
-        if ((subRect.GetWidth() == width) && (subRect.GetHeight() == height))
-            image.Paste(*this, pos.x, pos.y);
+        // insertion point is needed in destination coordinates.
+        // NB: it is not always "pos"!
+        wxPoint ptInsert = srcRect.GetTopLeft() + pos;
+
+        if ((srcRect.GetWidth() == width) && (srcRect.GetHeight() == height))
+            image.Paste(*this, ptInsert.x, ptInsert.y);
         else
-            image.Paste(GetSubImage(subRect), pos.x, pos.y);
+            image.Paste(GetSubImage(srcRect), ptInsert.x, ptInsert.y);
     }
 
     return image;
@@ -1424,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;
 
@@ -1448,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<unsigned char>(luma);
+            wxColour::MakeGrey(dest + 0, dest + 1, dest + 2, weight_r, weight_g, weight_b);
         }
     }
 
@@ -1502,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") );
@@ -2297,8 +2341,6 @@ bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index)
     if ( !handler.LoadFile(this, stream, true/*verbose*/, index) )
         return false;
 
-    M_IMGDATA->m_type = handler.GetType();
-
     // rescale the image to the specified size if needed
     if ( maxWidth || maxHeight )
     {
@@ -2319,6 +2361,9 @@ bool wxImage::DoLoad(wxImageHandler& handler, wxInputStream& stream, int index)
             Rescale(width, height, wxIMAGE_QUALITY_HIGH);
     }
 
+    // Set this after Rescale, which currently does not preserve it
+    M_IMGDATA->m_type = handler.GetType();
+
     return true;
 }