+ wxCHECK_RET( Ok(), wxT("invalid image") );
+ wxCHECK_RET( image.Ok(), wxT("invalid image") );
+
+ int xx = 0;
+ int yy = 0;
+ int width = image.GetWidth();
+ int height = image.GetHeight();
+
+ if (x < 0)
+ {
+ xx = -x;
+ width += x;
+ }
+ if (y < 0)
+ {
+ yy = -y;
+ height += y;
+ }
+
+ if ((x+xx)+width > M_IMGDATA->m_width)
+ width = M_IMGDATA->m_width - (x+xx);
+ if ((y+yy)+height > M_IMGDATA->m_height)
+ height = M_IMGDATA->m_height - (y+yy);
+
+ if (width < 1) return;
+ if (height < 1) return;
+
+ if ((!HasMask() && !image.HasMask()) ||
+ ((HasMask() && image.HasMask() &&
+ (GetMaskRed()==image.GetMaskRed()) &&
+ (GetMaskGreen()==image.GetMaskGreen()) &&
+ (GetMaskBlue()==image.GetMaskBlue()))))
+ {
+ width *= 3;
+ 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++)
+ {
+ memcpy( target_data, source_data, width );
+ source_data += source_step;
+ target_data += target_step;
+ }
+ return;
+ }
+
+ if (!HasMask() && image.HasMask())
+ {
+ unsigned char r = image.GetMaskRed();
+ unsigned char g = image.GetMaskGreen();
+ unsigned char b = image.GetMaskBlue();
+
+ width *= 3;
+ 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; 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") );
+
+ char unsigned *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::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 );
+
+ char unsigned *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;
+
+ char unsigned *srcd = M_IMGDATA->m_data;
+ char unsigned *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;
+}
+
+void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ int w = M_IMGDATA->m_width;
+ int h = M_IMGDATA->m_height;
+
+ wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), wxT("invalid image index") );
+
+ long pos = (y * w + x) * 3;
+
+ M_IMGDATA->m_data[ pos ] = r;
+ M_IMGDATA->m_data[ pos+1 ] = g;
+ M_IMGDATA->m_data[ pos+2 ] = b;
+}
+
+unsigned char wxImage::GetRed( int x, int y ) const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ int w = M_IMGDATA->m_width;
+ int h = M_IMGDATA->m_height;
+
+ wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
+
+ long pos = (y * w + x) * 3;
+
+ return M_IMGDATA->m_data[pos];
+}
+
+unsigned char wxImage::GetGreen( int x, int y ) const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ int w = M_IMGDATA->m_width;
+ int h = M_IMGDATA->m_height;
+
+ wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
+
+ long pos = (y * w + x) * 3;
+
+ return M_IMGDATA->m_data[pos+1];
+}
+
+unsigned char wxImage::GetBlue( int x, int y ) const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ int w = M_IMGDATA->m_width;
+ int h = M_IMGDATA->m_height;
+
+ wxCHECK_MSG( (x>=0) && (y>=0) && (x<w) && (y<h), 0, wxT("invalid image index") );
+
+ long pos = (y * w + x) * 3;
+
+ return M_IMGDATA->m_data[pos+2];
+}
+
+bool wxImage::Ok() const
+{
+ // image of 0 width or height can't be considered ok - at least because it
+ // causes crashes in ConvertToBitmap() if we don't catch it in time
+ wxImageRefData *data = M_IMGDATA;
+ return data && data->m_ok && data->m_width && data->m_height;
+}
+
+char unsigned *wxImage::GetData() const
+{
+ wxCHECK_MSG( Ok(), (char unsigned *)NULL, wxT("invalid image") );
+
+ return M_IMGDATA->m_data;
+}
+
+void wxImage::SetData( char unsigned *data )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ wxImageRefData *newRefData = new wxImageRefData();
+
+ newRefData->m_width = M_IMGDATA->m_width;
+ newRefData->m_height = M_IMGDATA->m_height;
+ newRefData->m_data = data;
+ newRefData->m_ok = TRUE;
+ newRefData->m_maskRed = M_IMGDATA->m_maskRed;
+ newRefData->m_maskGreen = M_IMGDATA->m_maskGreen;
+ newRefData->m_maskBlue = M_IMGDATA->m_maskBlue;
+ newRefData->m_hasMask = M_IMGDATA->m_hasMask;
+
+ UnRef();
+
+ m_refData = newRefData;
+}
+
+void wxImage::SetData( char unsigned *data, int new_width, int new_height )
+{
+ wxImageRefData *newRefData = new wxImageRefData();
+
+ if (m_refData)
+ {
+ newRefData->m_width = new_width;
+ newRefData->m_height = new_height;
+ newRefData->m_data = data;
+ newRefData->m_ok = TRUE;
+ newRefData->m_maskRed = M_IMGDATA->m_maskRed;
+ newRefData->m_maskGreen = M_IMGDATA->m_maskGreen;
+ newRefData->m_maskBlue = M_IMGDATA->m_maskBlue;
+ newRefData->m_hasMask = M_IMGDATA->m_hasMask;
+ }
+ else
+ {
+ newRefData->m_width = new_width;
+ newRefData->m_height = new_height;
+ newRefData->m_data = data;
+ newRefData->m_ok = TRUE;
+ }
+
+ UnRef();
+
+ m_refData = newRefData;
+}
+
+void wxImage::SetMaskColour( unsigned char r, unsigned char g, unsigned char b )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ M_IMGDATA->m_maskRed = r;
+ M_IMGDATA->m_maskGreen = g;
+ M_IMGDATA->m_maskBlue = b;
+ M_IMGDATA->m_hasMask = TRUE;
+}
+
+unsigned char wxImage::GetMaskRed() const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ return M_IMGDATA->m_maskRed;
+}
+
+unsigned char wxImage::GetMaskGreen() const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ return M_IMGDATA->m_maskGreen;
+}
+
+unsigned char wxImage::GetMaskBlue() const
+{
+ wxCHECK_MSG( Ok(), 0, wxT("invalid image") );
+
+ return M_IMGDATA->m_maskBlue;
+}
+
+void wxImage::SetMask( bool mask )
+{
+ wxCHECK_RET( Ok(), wxT("invalid image") );
+
+ M_IMGDATA->m_hasMask = mask;
+}
+
+bool wxImage::HasMask() const
+{
+ wxCHECK_MSG( Ok(), FALSE, wxT("invalid image") );
+
+ return M_IMGDATA->m_hasMask;
+}
+
+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;
+}
+
+
+bool wxImage::FindFirstUnusedColour(
+ unsigned char *r, unsigned char *g, unsigned char *b,
+ unsigned char startR, unsigned char startG, unsigned char startB) const
+{
+ wxImageHistogram histogram;
+ unsigned long key;
+
+ ComputeHistogram(histogram);
+
+ unsigned char r2 = startR;
+ unsigned char g2 = startG;
+ unsigned char b2 = startB;
+
+ key = (r2 << 16) | (g2 << 8) | b2;
+
+ while ( histogram.find(key) != histogram.end() )
+ {
+ // color already used
+ r2++;
+ if ( r2 >= 255 )
+ {
+ r2 = 0;
+ g2++;
+ if ( g2 >= 255 )
+ {
+ g2 = 0;
+ b2++;
+ if ( b2 >= 255 )
+ {
+ wxLogError( _("GetUnusedColour:: No Unused Color in image ") );
+ return FALSE;
+ }
+ }
+ }
+
+ key = (r2 << 16) | (g2 << 8) | b2;
+ }
+
+ if (r) *r = r2;
+ if (g) *g = g2;
+ if (b) *b = b2;