]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/image.cpp
Applied socket destruction bug patch
[wxWidgets.git] / src / common / image.cpp
index 0a12ff78478ee9a297d438ec2b97ed67e8204254..2a8b2013ff0076ebd8afff5877a124c9dec08f2a 100644 (file)
 #include "wx/utils.h"
 #include "wx/math.h"
 
+#if wxUSE_XPM
+#include "wx/xpmdecod.h"
+#endif
+
 // For memcpy
 #include <string.h>
 
@@ -159,6 +163,29 @@ wxImage::wxImage( const wxImage* image )
     if (image) Ref(*image);
 }
 
+wxImage::wxImage( const char** xpmData )
+{
+    Create(xpmData);
+}
+
+wxImage::wxImage( char** xpmData )
+{
+    Create((const char**) xpmData);
+}
+
+bool wxImage::Create( const char** xpmData )
+{
+#if wxUSE_XPM
+    UnRef();
+    
+    wxXPMDecoder decoder;
+    (*this) = decoder.ReadData(xpmData);
+    return Ok();
+#else
+    return false;
+#endif
+}
+
 bool wxImage::Create( int width, int height, bool clear )
 {
     UnRef();
@@ -279,6 +306,11 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
     unsigned char maskRed = 0;
     unsigned char maskGreen = 0;
     unsigned char maskBlue =0 ;
+
+    unsigned char *source_data = M_IMGDATA->m_data;
+    unsigned char *target_data = data;
+    unsigned char *source_alpha = 0 ;
+    unsigned char *target_alpha = 0 ;
     if (M_IMGDATA->m_hasMask)
     {
         hasMask = true ;
@@ -290,8 +322,15 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
                              M_IMGDATA->m_maskGreen,
                              M_IMGDATA->m_maskBlue );
     }
-    char unsigned *source_data = M_IMGDATA->m_data;
-    char unsigned *target_data = data;
+    else
+    {
+        source_alpha = M_IMGDATA->m_alpha ;
+        if ( source_alpha )
+        {
+            image.SetAlpha() ;
+            target_alpha = image.GetAlpha() ;
+        }
+    }
 
     for (long y = 0; y < height; y++)
     {
@@ -300,6 +339,7 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
             unsigned long avgRed = 0 ;
             unsigned long avgGreen = 0;
             unsigned long avgBlue = 0;
+            unsigned long avgAlpha = 0 ;
             unsigned long counter = 0 ;
             // determine average
             for ( int y1 = 0 ; y1 < yFactor ; ++y1 )
@@ -311,11 +351,18 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
                     unsigned char red = pixel[0] ;
                     unsigned char green = pixel[1] ;
                     unsigned char blue = pixel[2] ;
+                    unsigned char alpha = 255  ;
+                    if ( source_alpha )
+                        alpha = *(source_alpha + y_offset + x * xFactor + x1) ;
                     if ( !hasMask || red != maskRed || green != maskGreen || blue != maskBlue )
                     {
-                        avgRed += red ;
-                        avgGreen += green ;
-                        avgBlue += blue ;
+                        if ( alpha > 0 )
+                        {
+                            avgRed += red ;
+                            avgGreen += green ;
+                            avgBlue += blue ;
+                        }
+                        avgAlpha += alpha ;
                         counter++ ;
                     }
                 }
@@ -328,6 +375,8 @@ wxImage wxImage::ShrinkBy( int xFactor , int yFactor ) const
             }
             else
             {
+                if ( source_alpha )
+                    *(target_alpha++) = (unsigned char)(avgAlpha / counter ) ;
                 *(target_data++) = (unsigned char)(avgRed / counter);
                 *(target_data++) = (unsigned char)(avgGreen / counter);
                 *(target_data++) = (unsigned char)(avgBlue / counter);
@@ -372,15 +421,26 @@ wxImage wxImage::Scale( int width, int height ) const
 
     wxCHECK_MSG( data, image, wxT("unable to create image") );
 
+    unsigned char *source_data = M_IMGDATA->m_data;
+    unsigned char *target_data = data;
+    unsigned char *source_alpha = 0 ;
+    unsigned char *target_alpha = 0 ;
+    
     if (M_IMGDATA->m_hasMask)
     {
         image.SetMaskColour( M_IMGDATA->m_maskRed,
                              M_IMGDATA->m_maskGreen,
                              M_IMGDATA->m_maskBlue );
     }
-
-    unsigned char *source_data = M_IMGDATA->m_data;
-    unsigned char *target_data = data;
+    else
+    {
+        source_alpha = M_IMGDATA->m_alpha ;
+        if ( source_alpha )
+        {
+            image.SetAlpha() ;
+            target_alpha = image.GetAlpha() ;
+        }
+    }
 
     long x_delta = (old_width<<16) / width;
     long y_delta = (old_height<<16) / height;
@@ -391,15 +451,19 @@ wxImage wxImage::Scale( int width, int height ) const
     for ( long j = 0; j < height; j++ )
         {
         unsigned char* src_line = &source_data[(y>>16)*old_width*3];
-
+        unsigned char* src_alpha_line = source_alpha ? &source_alpha[(y>>16)*old_width] : 0 ;
+        
         long x = 0;
         for ( long i = 0; i < width; i++ )
         {
              unsigned char* src_pixel = &src_line[(x>>16)*3];
+             unsigned char* src_alpha_pixel = source_alpha ? &src_alpha_line[(x>>16)] : 0 ;
              dest_pixel[0] = src_pixel[0];
              dest_pixel[1] = src_pixel[1];
              dest_pixel[2] = src_pixel[2];
              dest_pixel += 3;
+             if ( source_alpha )
+                *(target_alpha++) = *src_alpha_pixel ;
              x += x_delta;
         }
 
@@ -875,6 +939,44 @@ unsigned char *wxImage::GetAlpha() const
     return M_IMGDATA->m_alpha;
 }
 
+void wxImage::InitAlpha()
+{
+    wxCHECK_RET( !HasAlpha(), wxT("image already has an alpha channel") );
+
+    // initialize memory for alpha channel
+    SetAlpha();
+
+    unsigned char *alpha = M_IMGDATA->m_alpha;
+    const size_t lenAlpha = M_IMGDATA->m_width * M_IMGDATA->m_height;
+
+    static const unsigned char ALPHA_TRANSPARENT = 0;
+    static const unsigned char ALPHA_OPAQUE = 0xff;
+    if ( HasMask() )
+    {
+        // use the mask to initialize the alpha channel.
+        const unsigned char * const alphaEnd = alpha + lenAlpha;
+
+        const unsigned char mr = M_IMGDATA->m_maskRed;
+        const unsigned char mg = M_IMGDATA->m_maskGreen;
+        const unsigned char mb = M_IMGDATA->m_maskBlue;
+        for ( unsigned char *src = M_IMGDATA->m_data;
+              alpha < alphaEnd;
+              src += 3, alpha++ )
+        {
+            *alpha = (src[0] == mr && src[1] == mg && src[2] == mb)
+                            ? ALPHA_TRANSPARENT
+                            : ALPHA_OPAQUE;
+        }
+
+        M_IMGDATA->m_hasMask = false;
+    }
+    else // no mask
+    {
+        // make the image fully opaque
+        memset(alpha, ALPHA_OPAQUE, lenAlpha);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // mask support
 // ----------------------------------------------------------------------------
@@ -1089,8 +1191,6 @@ wxString wxImage::GetOption(const wxString& name) const
 
 int wxImage::GetOptionInt(const wxString& name) const
 {
-    wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
-
     return wxAtoi(GetOption(name));
 }