+ // Copy over the alpha channel from the original image
+ if ( image.HasAlpha() )
+ {
+ if ( !HasAlpha() )
+ InitAlpha();
+
+ unsigned char* source_data = image.GetAlpha() + xx + yy*image.GetWidth();
+ int source_step = image.GetWidth();
+
+ unsigned char* target_data = GetAlpha() + (x+xx) + (y+yy)*M_IMGDATA->m_width;
+ int target_step = M_IMGDATA->m_width;
+
+ for (int j = 0; j < height; j++,
+ source_data += source_step,
+ target_data += target_step)
+ {
+ memcpy( target_data, source_data, width );
+ }
+ }
+
+ if (!HasMask() && image.HasMask())
+ {
+ unsigned char r = image.GetMaskRed();
+ unsigned char g = image.GetMaskGreen();
+ unsigned char b = image.GetMaskBlue();
+
+ unsigned char* source_data = image.GetData() + xx*3 + yy*3*image.GetWidth();
+ int source_step = image.GetWidth()*3;
+
+ unsigned char* target_data = GetData() + (x+xx)*3 + (y+yy)*3*M_IMGDATA->m_width;
+ int target_step = M_IMGDATA->m_width*3;
+
+ for (int j = 0; j < height; j++)
+ {
+ for (int i = 0; i < width*3; i+=3)
+ {
+ if ((source_data[i] != r) ||
+ (source_data[i+1] != g) ||
+ (source_data[i+2] != b))
+ {
+ memcpy( target_data+i, source_data+i, 3 );
+ }
+ }
+ source_data += source_step;
+ target_data += target_step;
+ }
+ }
+}
+
+void wxImage::Replace( unsigned char r1, unsigned char g1, unsigned char b1,
+ unsigned char r2, unsigned char g2, unsigned char b2 )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ AllocExclusive();
+
+ unsigned char *data = GetData();
+
+ const int w = GetWidth();
+ const int h = GetHeight();
+
+ for (int j = 0; j < h; j++)
+ for (int i = 0; i < w; i++)
+ {
+ if ((data[0] == r1) && (data[1] == g1) && (data[2] == b1))
+ {
+ data[0] = r2;
+ data[1] = g2;
+ data[2] = b2;
+ }
+ data += 3;
+ }
+}
+
+wxImage wxImage::ConvertToGreyscale( double lr, double lg, double lb ) const
+{
+ wxImage image;
+
+ wxCHECK_MSG( Ok(), image, wxT("invalid image") );
+
+ image.Create(M_IMGDATA->m_width, M_IMGDATA->m_height, false);
+
+ unsigned char *dest = image.GetData();
+
+ wxCHECK_MSG( dest, image, wxT("unable to create image") );
+
+ unsigned char *src = M_IMGDATA->m_data;
+ bool hasMask = M_IMGDATA->m_hasMask;
+ unsigned char maskRed = M_IMGDATA->m_maskRed;
+ unsigned char maskGreen = M_IMGDATA->m_maskGreen;
+ unsigned char maskBlue = M_IMGDATA->m_maskBlue;
+
+ if ( hasMask )
+ image.SetMaskColour(maskRed, maskGreen, maskBlue);
+
+ const long size = M_IMGDATA->m_width * M_IMGDATA->m_height;
+ for ( long i = 0; i < size; i++, src += 3, dest += 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);
+ }
+ }
+
+ // copy the alpha channel, if any
+ if (HasAlpha())
+ {
+ const size_t alphaSize = GetWidth() * GetHeight();
+ unsigned char *alpha = (unsigned char*)malloc(alphaSize);
+ memcpy(alpha, GetAlpha(), alphaSize);
+ image.InitAlpha();
+ image.SetAlpha(alpha);
+ }
+
+ return image;
+}
+
+wxImage wxImage::ConvertToMono( unsigned char r, unsigned char g, unsigned char b ) const
+{
+ wxImage image;
+
+ wxCHECK_MSG( Ok(), image, wxT("invalid image") );
+
+ image.Create( M_IMGDATA->m_width, M_IMGDATA->m_height, false );
+
+ unsigned char *data = image.GetData();
+
+ wxCHECK_MSG( data, image, wxT("unable to create image") );
+
+ if (M_IMGDATA->m_hasMask)
+ {
+ if (M_IMGDATA->m_maskRed == r && M_IMGDATA->m_maskGreen == g &&
+ M_IMGDATA->m_maskBlue == b)
+ image.SetMaskColour( 255, 255, 255 );
+ else
+ image.SetMaskColour( 0, 0, 0 );
+ }
+
+ long size = M_IMGDATA->m_height * M_IMGDATA->m_width;
+
+ unsigned char *srcd = M_IMGDATA->m_data;
+ unsigned char *tard = image.GetData();
+
+ 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;
+ }
+
+ return image;
+}
+
+int wxImage::GetWidth() const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ return M_IMGDATA->m_width;
+}
+
+int wxImage::GetHeight() const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ return M_IMGDATA->m_height;
+}
+
+wxBitmapType wxImage::GetType() const
+{
+ wxCHECK_MSG( IsOk(), wxBITMAP_TYPE_INVALID, wxT("invalid image") );
+
+ return M_IMGDATA->m_type;
+}
+
+void wxImage::SetType(wxBitmapType type)
+{
+ wxCHECK_RET( IsOk(), "must create the image before setting its type");
+
+ // type can be wxBITMAP_TYPE_INVALID to reset the image type to default
+ wxASSERT_MSG( type != wxBITMAP_TYPE_MAX, "invalid bitmap type" );
+
+ M_IMGDATA->m_type = type;
+}
+
+long wxImage::XYToIndex(int x, int y) const
+{
+ if ( Ok() &&
+ x >= 0 && y >= 0 &&
+ x < M_IMGDATA->m_width && y < M_IMGDATA->m_height )
+ {
+ return y*M_IMGDATA->m_width + x;
+ }
+
+ return -1;
+}
+
+void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
+{
+ long pos = XYToIndex(x, y);
+ wxCHECK_RET( pos != -1, wxT("invalid image coordinates") );
+
+ AllocExclusive();
+
+ pos *= 3;
+
+ M_IMGDATA->m_data[ pos ] = r;
+ M_IMGDATA->m_data[ pos+1 ] = g;
+ M_IMGDATA->m_data[ pos+2 ] = b;
+}
+
+void wxImage::SetRGB( const wxRect& rect_, unsigned char r, unsigned char g, unsigned char b )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ AllocExclusive();
+
+ wxRect rect(rect_);
+ wxRect imageRect(0, 0, GetWidth(), GetHeight());
+ if ( rect == wxRect() )
+ {
+ rect = imageRect;
+ }
+ else
+ {
+ wxCHECK_RET( imageRect.Contains(rect.GetTopLeft()) &&
+ imageRect.Contains(rect.GetBottomRight()),
+ wxT("invalid bounding rectangle") );
+ }
+
+ int x1 = rect.GetLeft(),
+ y1 = rect.GetTop(),
+ x2 = rect.GetRight() + 1,
+ y2 = rect.GetBottom() + 1;
+
+ unsigned char *data wxDUMMY_INITIALIZE(NULL);
+ int x, y, width = GetWidth();
+ for (y = y1; y < y2; y++)
+ {
+ data = M_IMGDATA->m_data + (y*width + x1)*3;
+ for (x = x1; x < x2; x++)
+ {
+ *data++ = r;
+ *data++ = g;
+ *data++ = b;
+ }
+ }
+}
+
+unsigned char wxImage::GetRed( int x, int y ) const
+{
+ long pos = XYToIndex(x, y);
+ wxCHECK_MSG( pos != -1, 0, wxT("invalid image coordinates") );
+
+ pos *= 3;
+
+ return M_IMGDATA->m_data[pos];