X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/97fdfcc9fdc68c3510599bf483afcb34d8768057..30b5fc118f6fa8bad8cd3692ca42c164aa5007f9:/src/common/image.cpp diff --git a/src/common/image.cpp b/src/common/image.cpp index fcdc3d34e9..dc5fdf6c48 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -224,6 +224,29 @@ wxImage wxImage::GetSubImage( const wxRect &rect ) const return image; } +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; + } +} + void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b ) { wxCHECK_RET( Ok(), wxT("invalid image") ); @@ -860,7 +883,12 @@ wxBitmap wxImage::ConvertToBitmap() const { for(i=0; i #endif +wxBitmap wxImage::ConvertToMonoBitmap( unsigned char red, unsigned char green, unsigned char blue ) +{ + wxBitmap bitmap; + + wxCHECK_MSG( Ok(), bitmap, wxT("invalid image") ); + + int width = GetWidth(); + int height = GetHeight(); + + bitmap.SetHeight( height ); + bitmap.SetWidth( width ); + + bitmap.SetBitmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ) ); + + bitmap.SetDepth( 1 ); + + // Create picture image + + unsigned char *data_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); + + GdkImage *data_image = + gdk_image_new_bitmap( gdk_visual_get_system(), data_data, width, height ); + + // Create mask image + + GdkImage *mask_image = (GdkImage*) NULL; + + if (HasMask()) + { + unsigned char *mask_data = (unsigned char*)malloc( ((width >> 3)+8) * height ); + + mask_image = gdk_image_new_bitmap( gdk_visual_get_system(), mask_data, width, height ); + + wxMask *mask = new wxMask(); + mask->m_bitmap = gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, 1 ); + + bitmap.SetMask( mask ); + } + + int r_mask = GetMaskRed(); + int g_mask = GetMaskGreen(); + int b_mask = GetMaskBlue(); + + unsigned char* data = GetData(); + + int index = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + int r = data[index]; + index++; + int g = data[index]; + index++; + int b = data[index]; + index++; + + if (HasMask()) + { + if ((r == r_mask) && (b == b_mask) && (g == g_mask)) + gdk_image_put_pixel( mask_image, x, y, 1 ); + else + gdk_image_put_pixel( mask_image, x, y, 0 ); + } + + if ((r == red) && (b == blue) && (g == green)) + gdk_image_put_pixel( data_image, x, y, 1 ); + else + gdk_image_put_pixel( data_image, x, y, 0 ); + + } // for + } // for + + // Blit picture + + GdkGC *data_gc = gdk_gc_new( bitmap.GetBitmap() ); + + gdk_draw_image( bitmap.GetBitmap(), data_gc, data_image, 0, 0, 0, 0, width, height ); + + gdk_image_destroy( data_image ); + gdk_gc_unref( data_gc ); + + // Blit mask + + if (HasMask()) + { + GdkGC *mask_gc = gdk_gc_new( bitmap.GetMask()->GetBitmap() ); + + gdk_draw_image( bitmap.GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height ); + + gdk_image_destroy( mask_image ); + gdk_gc_unref( mask_gc ); + } + + return bitmap; +} + + wxBitmap wxImage::ConvertToBitmap() const { wxBitmap bitmap; @@ -1405,14 +1505,6 @@ wxBitmap wxImage::ConvertToBitmap() const gdk_image_put_pixel( mask_image, x, y, 0 ); } - if (HasMask()) - { - if ((r == r_mask) && (b == b_mask) && (g == g_mask)) - gdk_image_put_pixel( mask_image, x, y, 1 ); - else - gdk_image_put_pixel( mask_image, x, y, 0 ); - } - switch (bpp) { case 8: @@ -1541,16 +1633,37 @@ wxImage::wxImage( const wxBitmap &bitmap ) SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable } - GdkVisual *visual = (GdkVisual*) NULL; + int bpp = -1; + int red_shift_right = 0; + int green_shift_right = 0; + int blue_shift_right = 0; + int red_shift_left = 0; + int green_shift_left = 0; + int blue_shift_left = 0; + bool use_shift = FALSE; + if (bitmap.GetPixmap()) - visual = gdk_window_get_visual( bitmap.GetPixmap() ); - else - visual = gdk_window_get_visual( bitmap.GetBitmap() ); + { + GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() ); - if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent ); - int bpp = visual->depth; - if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15; + if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent ); + bpp = visual->depth; + if (bpp == 16) bpp = visual->red_prec + visual->green_prec + visual->blue_prec; + red_shift_right = visual->red_shift; + red_shift_left = 8-visual->red_prec; + green_shift_right = visual->green_shift; + green_shift_left = 8-visual->green_prec; + blue_shift_right = visual->blue_shift; + blue_shift_left = 8-visual->blue_prec; + + use_shift = (visual->type == GDK_VISUAL_TRUE_COLOR) || (visual->type == GDK_VISUAL_DIRECT_COLOR); + } + if (bitmap.GetBitmap()) + { + bpp = 1; + } + GdkColormap *cmap = gtk_widget_get_default_colormap(); long pos = 0; @@ -1558,40 +1671,38 @@ wxImage::wxImage( const wxBitmap &bitmap ) { for (int i = 0; i < bitmap.GetWidth(); i++) { - wxInt32 pixel = gdk_image_get_pixel( gdk_image, i, j ); - if (bpp <= 8) - { - data[pos] = cmap->colors[pixel].red >> 8; - data[pos+1] = cmap->colors[pixel].green >> 8; - data[pos+2] = cmap->colors[pixel].blue >> 8; - } else if (bpp == 15) + wxUint32 pixel = gdk_image_get_pixel( gdk_image, i, j ); + if (bpp == 1) + { + if (pixel == 0) + { + data[pos] = 0; + data[pos+1] = 0; + data[pos+2] = 0; + } + else + { + data[pos] = 255; + data[pos+1] = 255; + data[pos+2] = 255; + } + } + else if (use_shift) { -#if (wxBYTE_ORDER == wxBIG_ENDIAN) - // ? -#endif - data[pos] = (pixel >> 7) & 0xf8; - data[pos+1] = (pixel >> 2) & 0xf8; - data[pos+2] = (pixel << 3) & 0xf8; - } else if (bpp == 16) + data[pos] = (pixel >> red_shift_right) << red_shift_left; + data[pos+1] = (pixel >> green_shift_right) << green_shift_left; + data[pos+2] = (pixel >> blue_shift_right) << blue_shift_left; + } + else if (cmap->colors) { -#if (wxBYTE_ORDER == wxBIG_ENDIAN) - // ? -#endif - data[pos] = (pixel >> 8) & 0xf8; - data[pos+1] = (pixel >> 3) & 0xfc; - data[pos+2] = (pixel << 3) & 0xf8; - } else + data[pos] = cmap->colors[pixel].red >> 8; + data[pos+1] = cmap->colors[pixel].green >> 8; + data[pos+2] = cmap->colors[pixel].blue >> 8; + } + else { -#if (wxBYTE_ORDER == wxBIG_ENDIAN) - data[pos] = (pixel) & 0xff; // Red - data[pos+1] = (pixel >> 8) & 0xff; // Green - data[pos+2] = (pixel >> 16) & 0xff; // Blue -#else - data[pos] = (pixel >> 16) & 0xff; - data[pos+1] = (pixel >> 8) & 0xff; - data[pos+2] = pixel & 0xff; -#endif - } + wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") ); + } if (gdk_image_mask) { @@ -1629,6 +1740,179 @@ wxImage::wxImage( const wxBitmap &bitmap ) #include "wx/utils.h" #include +/* + +Date: Wed, 05 Jan 2000 11:45:40 +0100 +From: Frits Boel +To: julian.smart@ukonline.co.uk +Subject: Patch for Motif ConvertToBitmap + +Hi Julian, + +I've been working on a wxWin application for image processing. From the +beginning, I was surprised by the (lack of) speed of ConvertToBitmap, +till I looked in the source code of image.cpp. I saw that converting a +wxImage to a bitmap with 8-bit pixels is done with comparing every pixel +to the 256 colors of the palet. A very time-consuming piece of code! + +Because I wanted a faster application, I've made a 'patch' for this. In +short: every pixel of the image is compared to a sorted list with +colors. If the color is found in the list, the palette entry is +returned; if the color is not found, the color palette is searched and +then the palette entry is returned and the color added to the sorted +list. + +Maybe there is another method for this, namely changing the palette +itself (if the colors are known, as is the case with tiffs with a +colormap). I did not look at this, maybe someone else did? + +The code of the patch is attached, have a look on it, and maybe you will +ship it with the next release of wxMotif? + +Regards, + +Frits Boel +Software engineer at Hubrecht Laboratory, The Netherlands. + +*/ + +class wxSearchColor +{ +public: + wxSearchColor( void ); + wxSearchColor( int size, XColor *colors ); + ~wxSearchColor( void ); + + int SearchColor( int r, int g, int b ); +private: + int AddColor( unsigned int value, int pos ); + + int size; + XColor *colors; + unsigned int *color; + int *entry; + + int bottom; + int top; +}; + +wxSearchColor::wxSearchColor( void ) +{ + this->size = 0; + this->colors = (XColor*) NULL; + this->color = (unsigned int *) NULL; + this->entry = (int*) NULL; + + this->bottom = 0; + this->top = 0; +} + +wxSearchColor::wxSearchColor( int size, XColor *colors ) +{ + int i; + this->size = size; + this->colors = colors; + this->color = new unsigned int[size]; + this->entry = new int [size]; + + for (i = 0; i < this->size; i++ ) { + this->entry[i] = -1; + } + + this->bottom = this->top = ( size >> 1 ); +} + +wxSearchColor::~wxSearchColor( void ) +{ + if ( this->color ) delete this->color; + if ( this->entry ) delete this->entry; +} + +int wxSearchColor::SearchColor( int r, int g, int b ) +{ + unsigned int value = ( ( ( r * 256 ) + g ) * 256 ) + b; + int begin = this->bottom; + int end = this->top; + int middle; + + while ( begin <= end ) { + + middle = ( begin + end ) >> 1; + + if ( value == this->color[middle] ) { + return( this->entry[middle] ); + } else if ( value < this->color[middle] ) { + end = middle - 1; + } else { + begin = middle + 1; + } + + } + + return AddColor( value, middle ); +} + +int wxSearchColor::AddColor( unsigned int value, int pos ) +{ + int i; + int pixel = -1; + int max = 3 * (65536); + for ( i = 0; i < 256; i++ ) { + int rdiff = ((value >> 8) & 0xFF00 ) - colors[i].red; + int gdiff = ((value ) & 0xFF00 ) - colors[i].green; + int bdiff = ((value << 8) & 0xFF00 ) - colors[i].blue; + int sum = abs (rdiff) + abs (gdiff) + abs (bdiff); + if (sum < max) { pixel = i; max = sum; } + } + + if ( this->entry[pos] < 0 ) { + this->color[pos] = value; + this->entry[pos] = pixel; + } else if ( value < this->color[pos] ) { + + if ( this->bottom > 0 ) { + for ( i = this->bottom; i < pos; i++ ) { + this->color[i-1] = this->color[i]; + this->entry[i-1] = this->entry[i]; + } + this->bottom--; + this->color[pos-1] = value; + this->entry[pos-1] = pixel; + } else if ( this->top < this->size-1 ) { + for ( i = this->top; i >= pos; i-- ) { + this->color[i+1] = this->color[i]; + this->entry[i+1] = this->entry[i]; + } + this->top++; + this->color[pos] = value; + this->entry[pos] = pixel; + } + + } else { + + if ( this->top < this->size-1 ) { + for ( i = this->top; i > pos; i-- ) { + this->color[i+1] = this->color[i]; + this->entry[i+1] = this->entry[i]; + } + this->top++; + this->color[pos+1] = value; + this->entry[pos+1] = pixel; + } else if ( this->bottom > 0 ) { + for ( i = this->bottom; i < pos; i++ ) { + this->color[i-1] = this->color[i]; + this->entry[i-1] = this->entry[i]; + } + this->bottom--; + this->color[pos] = value; + this->entry[pos] = pixel; + } + + } + + return( pixel ); +} + wxBitmap wxImage::ConvertToBitmap() const { wxBitmap bitmap; @@ -1719,6 +2003,7 @@ wxBitmap wxImage::ConvertToBitmap() const XQueryColors( dpy, cmap, colors, 256 ); } + wxSearchColor scolor( 256, colors ); unsigned char* data = GetData(); int index = 0; @@ -1747,6 +2032,7 @@ wxBitmap wxImage::ConvertToBitmap() const { case 8: { +#if 0 // Old, slower code int pixel = -1; /* if (wxTheApp->m_colorCube) @@ -1769,6 +2055,10 @@ wxBitmap wxImage::ConvertToBitmap() const /* } */ +#endif + + // And this is all to get the 'right' color... + int pixel = scolor.SearchColor( r, g, b ); XPutPixel( data_image, x, y, pixel ); break; }