]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/image.cpp
Changes to allow Cygwin to compile in non-PCH mode
[wxWidgets.git] / src / common / image.cpp
index 99b92a463ddcbd090123951dff9dac2cf650c9fb..3138c68f0bfa0f48982b0922c41883739c42e837 100644 (file)
 #endif
 
 #include "wx/image.h"
+#include "wx/bitmap.h"
 #include "wx/debug.h"
 #include "wx/log.h"
+#ifdef wxUSE_LIBPNG
 #include "../png/png.h"
+#endif
 #include "wx/filefn.h"
 
+#ifdef __WXMSW__
+#include <windows.h>
+#endif
+
 //-----------------------------------------------------------------------------
 // wxImage
 //-----------------------------------------------------------------------------
@@ -391,7 +398,9 @@ wxImageHandler *wxImage::FindHandler( long bitmapType )
 void wxImage::InitStandardHandlers()
 {
     AddHandler( new wxBMPHandler );
+#ifdef wxUSE_LIBPNG
     AddHandler( new wxPNGHandler );
+#endif
 }
 
 void wxImage::CleanUpHandlers()
@@ -429,186 +438,192 @@ bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), const wxString& WXUNUSE
 // wxPNGHandler
 //-----------------------------------------------------------------------------
 
+#ifdef wxUSE_LIBPNG
+
 #if !USE_SHARED_LIBRARIES
 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler)
 #endif
   
 bool wxPNGHandler::LoadFile( wxImage *image, const wxString& name )
 {
-   FILE               *f;
-   png_structp         png_ptr;
-   png_infop           info_ptr;
-   unsigned char      *ptr, **lines, *ptr2;
-   int                 transp,bit_depth,color_type,interlace_type;
-   png_uint_32         width, height;
-   unsigned int               i;
-
-   image->Destroy();
+    image->Destroy();
    
-   transp = 0;
-   png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
-   if (!png_ptr) return FALSE;
-
-   info_ptr = png_create_info_struct( png_ptr );
-   if (!info_ptr)
-   {
-     png_destroy_read_struct( &png_ptr, NULL, NULL );
-     return FALSE;
-   }
-
-   if (setjmp(png_ptr->jmpbuf))
-   {
-     png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-     return FALSE;
-   }
-
-   if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-   {
-     png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-     return FALSE;
-   }
+    png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 
+                                                  (voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL );
+    if (!png_ptr) return FALSE;
+
+    png_infop info_ptr = png_create_info_struct( png_ptr );
+    if (!info_ptr)
+    {
+        png_destroy_read_struct( &png_ptr, (png_infopp) NULL, (png_infopp) NULL );
+        return FALSE;
+    }
+
+    if (setjmp(png_ptr->jmpbuf))
+    {
+        png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+        return FALSE;
+    }
+
+    if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+    {
+        png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+        return FALSE;
+    }
    
-   f = fopen( name, "rb" );
-   png_init_io( png_ptr, f );
+    FILE *f = fopen( name, "rb" );
+    png_init_io( png_ptr, f );
    
-   png_read_info( png_ptr, info_ptr );
-   png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL );
+    png_uint_32 width,height;
+    int bit_depth,color_type,interlace_type;
+
+    png_read_info( png_ptr, info_ptr );
+    png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, (int*) NULL, (int*) NULL );
    
-   if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
+    if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_expand( png_ptr );
    
-   png_set_strip_16( png_ptr );
-   png_set_packing( png_ptr );
-   if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr );
-   png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
+    png_set_strip_16( png_ptr );
+    png_set_packing( png_ptr );
+    if (png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand( png_ptr );
+    png_set_filler( png_ptr, 0xff, PNG_FILLER_AFTER );
    
-   image->Create( width, height );
+    image->Create( width, height );
    
-   if (!image->Ok())
-   {
-     png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-     return FALSE;
-   }
+    if (!image->Ok())
+    {
+        png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+        return FALSE;
+    }
    
-   lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
-   if (lines == NULL)
-   {
-     image->Destroy();
-     png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-     return FALSE;
-   }
+    unsigned char **lines = (unsigned char **)malloc( height * sizeof(unsigned char *) );
+    if (lines == NULL)
+    {
+        image->Destroy();
+        png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+        return FALSE;
+    }
    
-   for (i = 0; i < height; i++)
-   {
-     if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
-     {
-       image->Destroy();
-       for (unsigned int n = 0; n < i; n++) free( lines[n] );
-       free( lines );
-       png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-       return FALSE;
-     }
-  }
+    for (unsigned int i = 0; i < height; i++)
+    {
+        if ((lines[i] = (unsigned char *)malloc(width * (sizeof(unsigned char) * 4))) == NULL)
+        {
+            image->Destroy();
+            for (unsigned int n = 0; n < i; n++) free( lines[n] );
+            free( lines );
+            png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+            return FALSE;
+        }
+    }
      
-   png_read_image( png_ptr, lines );
-   png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
-   ptr = image->GetData();
-   if ((color_type == PNG_COLOR_TYPE_GRAY) ||
-       (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
-     {
+  
+    int transp = 0;
+    png_read_image( png_ptr, lines );
+    png_destroy_read_struct( &png_ptr, &info_ptr, (png_infopp) NULL );
+    unsigned char *ptr = image->GetData();
+    if ((color_type == PNG_COLOR_TYPE_GRAY) ||
+        (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+    {
        for (unsigned int y = 0; y < height; y++)
-         {
-            ptr2 = lines[y];
-            for (unsigned int x = 0; x < width; x++)
-              {
-                 unsigned char r = *ptr2++;
-                 unsigned char a = *ptr2++;
-                 if (a < 128)
-                   {
-                      *ptr++ = 255;
-                      *ptr++ = 0;
-                      *ptr++ = 255;
-                      transp = 1;
-                   }
-                 else
-                   {
-                      *ptr++ = r;
-                      *ptr++ = r;
-                      *ptr++ = r;
-                   }
-              }
-         }
-     }
-   else
-     {
+       {
+           unsigned char *ptr2 = lines[y];
+           for (unsigned int x = 0; x < width; x++)
+           {
+               unsigned char r = *ptr2++;
+               unsigned char a = *ptr2++;
+               if (a < 128)
+               {
+                   *ptr++ = 255;
+                   *ptr++ = 0;
+                   *ptr++ = 255;
+                   transp = 1;
+               }
+               else
+               {
+                   *ptr++ = r;
+                   *ptr++ = r;
+                   *ptr++ = r;
+               }
+           }
+       }
+    }
+    else
+    {
        for (unsigned int y = 0; y < height; y++)
-         {
-            ptr2 = lines[y];
-            for (unsigned int x = 0; x < width; x++)
-              {
-                 unsigned char r = *ptr2++;
-                 unsigned char g = *ptr2++;
-                 unsigned char b = *ptr2++;
-                 unsigned char a = *ptr2++;
-                 if (a < 128)
-                   {
-                      *ptr++ = 255;
-                      *ptr++ = 0;
-                      *ptr++ = 255;
-                      transp = 1;
-                   }
-                 else
-                   {
-                      if ((r == 255) && (g == 0) && (b == 255)) r = 254;
-                      *ptr++ = r;
-                      *ptr++ = g;
-                      *ptr++ = b;
-                   }
-              }
-         }
-     }
-   for (i = 0; i < height; i++) free( lines[i] );
-   free( lines );
-   if (transp)
-     image->SetMaskColour( 255, 0, 255 );
-   else
-     image->SetMask( FALSE );
+       {
+           unsigned char *ptr2 = lines[y];
+           for (unsigned int x = 0; x < width; x++)
+           {
+               unsigned char r = *ptr2++;
+               unsigned char g = *ptr2++;
+               unsigned char b = *ptr2++;
+               unsigned char a = *ptr2++;
+               if (a < 128)
+               {
+                   *ptr++ = 255;
+                   *ptr++ = 0;
+                   *ptr++ = 255;
+                   transp = 1;
+               }
+               else
+               {
+                   if ((r == 255) && (g == 0) && (b == 255)) r = 254;
+                   *ptr++ = r;
+                   *ptr++ = g;
+                   *ptr++ = b;
+               }
+           }
+       }
+    }
+    
+    for (unsigned int j = 0; j < height; j++) free( lines[j] );
+    free( lines );
+    
+    if (transp)
+    {
+        image->SetMaskColour( 255, 0, 255 );
+    }
+    else
+    {
+        image->SetMask( FALSE );
+    }
    
-   return TRUE;
+    return TRUE;
 }
 
 
 bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
 {
-  FILE *f = fopen( name, "wb" );
-  if (f)
-  {
-    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    FILE *f = fopen( name, "wb" );
+    if (!f) return FALSE;
+    
+    png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 
+                                                       (voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL);
     if (!png_ptr) 
     { 
-      fclose( f ); 
-      return FALSE; 
+        fclose( f ); 
+        return FALSE; 
     }
     
     png_infop info_ptr = png_create_info_struct(png_ptr);
     if (info_ptr == NULL)
     {
-      fclose(f);
-      png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
-      return FALSE;
+        fclose(f);
+        png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
+        return FALSE;
     }
     
     if (setjmp(png_ptr->jmpbuf))
     {
-      fclose( f );
-      png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
-      return FALSE;
+        fclose( f );
+        png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
+        return FALSE;
     }
     
     png_init_io( png_ptr, f );
     png_set_IHDR( png_ptr, info_ptr, image->GetWidth(), image->GetHeight(), 8,
-                 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+                 PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
                  PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-                         
+
     png_color_8 sig_bit;
     sig_bit.red = 8;
     sig_bit.green = 8;
@@ -622,38 +637,47 @@ bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
     unsigned char *data = (unsigned char *)malloc( image->GetWidth()*4 );
     if (!data)
     {
-      fclose( f );
-      png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
-      return FALSE;
+        fclose( f );
+        png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
+        return FALSE;
     }
     
     for (int y = 0; y < image->GetHeight(); y++)
     {
-      unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3);
-      for (int x = 0; x < image->GetWidth(); x++)
-      {
-       data[(x << 2) + 0] = *ptr++;
-       data[(x << 2) + 1] = *ptr++;
-       data[(x << 2) + 2] = *ptr++;
-       if ((data[(x << 2) + 0] == image->GetMaskRed()) &&
-           (data[(x << 2) + 1] == image->GetMaskGreen()) &&
-           (data[(x << 2) + 2] == image->GetMaskBlue()))
-          data[(x << 2) + 3] = 0;
-       else
-         data[(x << 2) + 3] = 255;
-      }
-      png_bytep row_ptr = data;
-      png_write_rows( png_ptr, &row_ptr, 1 );
+        unsigned char *ptr = image->GetData() + (y * image->GetWidth() * 3);
+        for (int x = 0; x < image->GetWidth(); x++)
+        {
+           data[(x << 2) + 0] = *ptr++;
+           data[(x << 2) + 1] = *ptr++;
+           data[(x << 2) + 2] = *ptr++;
+           if ((data[(x << 2) + 0] == image->GetMaskRed()) &&
+               (data[(x << 2) + 1] == image->GetMaskGreen()) &&
+               (data[(x << 2) + 2] == image->GetMaskBlue()))
+           {
+                data[(x << 2) + 3] = 0;
+           }
+           else
+           {
+               data[(x << 2) + 3] = 255;
+           }
+        }
+        png_bytep row_ptr = data;
+        png_write_rows( png_ptr, &row_ptr, 1 );
     }
+    
     free(data);
     png_write_end( png_ptr, info_ptr );
-    png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
+    png_destroy_write_struct( &png_ptr, (png_infopp) NULL );
 
     fclose(f);
-  }
-  return TRUE;
+    
+    return TRUE;
 }
 
+#endif 
+
+  // wxUSE_LIBPNG
+
 //-----------------------------------------------------------------------------
 // wxBMPHandler
 //-----------------------------------------------------------------------------
@@ -682,6 +706,9 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
 #define BI_RGB       0
 #define BI_RLE8      1
 #define BI_RLE4      2
+#endif
+
+#ifndef BI_BITFIELDS
 #define BI_BITFIELDS 3
 #endif
 
@@ -708,13 +735,13 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    int height = (int)dbuf[1];
    if (width > 32767)
      {
-       fprintf(stderr, "IMLIB ERROR: Image width > 32767 pixels for file\n");
+       wxLogError( "Image width > 32767 pixels for file\n" );
        fclose(file);
        return FALSE;
      }
    if (height > 32767)
      {
-       fprintf(stderr, "IMLIB ERROR: Image height > 32767 pixels for file\n");
+       wxLogError( "Image height > 32767 pixels for file\n" );
        fclose(file);
        return FALSE;
      }
@@ -724,7 +751,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    bpp = (int)word;
    if (bpp != 1 && bpp != 4 && bpp != 8 && bpp && 16 && bpp != 24 && bpp != 32)
      {
-       fprintf(stderr, "IMLIB ERROR: unknown bitdepth in file\n");
+       wxLogError( "unknown bitdepth in file\n" );
        fclose(file);
        return FALSE;
      }
@@ -732,7 +759,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    comp = (int)dbuf[0];
    if (comp != BI_RGB && comp != BI_RLE4 && comp != BI_RLE8 && comp != BI_BITFIELDS)
      {
-       fprintf(stderr, "IMLIB ERROR: unknown encoding in Windows BMP file\n");
+        wxLogError( "unknown encoding in Windows BMP file\n" );
        fclose(file);
        return FALSE;
      }
@@ -743,7 +770,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    /* some more sanity checks */
    if (((comp == BI_RLE4) && (bpp != 4)) || ((comp == BI_RLE8) && (bpp != 8)) || ((comp == BI_BITFIELDS) && (bpp != 16 && bpp != 32)))
      {
-       fprintf(stderr, "IMLIB ERROR: encoding of BMP doesn't match bitdepth\n");
+        wxLogError( "encoding of BMP doesn't match bitdepth\n" );
        fclose(file);
        return FALSE;
      }
@@ -753,7 +780,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
 
        if (!cmap)
          {
-            fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for color map in BMP file\n");
+            wxLogError( "Cannot allocate RAM for color map in BMP file\n" );
             fclose(file);
             return FALSE;
          }
@@ -765,7 +792,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    ptr = image->GetData();
    if (!ptr)
      {
-       fprintf(stderr, "IMLIB ERROR: Cannot allocate RAM for RGB data in file\n");
+        wxLogError( "Cannot allocate RAM for RGB data in file\n" );
        fclose(file);
        if (cmap)
           free(cmap);
@@ -827,7 +854,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
      }
 
    /*
-    * REading the image data
+    * Reading the image data
     */
    fseek(file, offset, SEEK_SET);
    data = ptr;
@@ -880,7 +907,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
                    {
                       if (comp == BI_RLE4)
                         {
-                           fprintf(stderr, "can't deal with 4bit encoded yet.\n");
+                           wxLogError( "can't deal with 4bit encoded yet.\n");
                            image->Destroy();
                            free(cmap);
                            return FALSE;
@@ -1101,28 +1128,28 @@ wxBitmap wxImage::ConvertToBitmap() const
     for( int i=0; i<width*height; i++ )
     {
       if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
-      {
-        *(ptbits++) = zero;
-        *(ptbits++) = zero;
-        *(ptbits++) = zero;
-      }
-      else
       {
         *(ptbits++) = one;
         *(ptbits++) = one;
         *(ptbits++) = one;
       }
+      else
+      {
+        *(ptbits++) = zero;
+        *(ptbits++) = zero;
+        *(ptbits++) = zero;
+      }
     }
     hbitmap = ::CreateBitmap( (WORD)width, (WORD)height, 1, 1, NULL );
     ::SetDIBits( hdc, hbitmap, 0, (WORD)height, lpBits, lpDIBh, DIB_RGB_COLORS);
-    wxMask bmpmask;
-    bmpmask.SetMaskBitmap( (WXHBITMAP) hbitmap );
-    bitmap.SetMask( &bmpmask );
+    wxMask *mask = new wxMask();
+    mask->SetMaskBitmap( (WXHBITMAP) hbitmap );
+    bitmap.SetMask( mask );
 
 /* The following can also be used but is slow to run
     wxColour colour( GetMaskRed(), GetMaskGreen(), GetMaskBlue());
-    wxMask bmpmask( bitmap, colour );
-    bitmap.SetMask( &bmpmask );
+    wxMask *mask = new wxMask( bitmap, colour );
+    bitmap.SetMask( mask );
 */
   }
 
@@ -1236,3 +1263,260 @@ wxImage::wxImage( const wxBitmap &bitmap )
 
 #endif
 
+#ifdef __WXGTK__
+
+#include "gtk/gtk.h"
+#include "gdk/gdk.h"
+#include "gdk/gdkx.h"
+
+wxBitmap wxImage::ConvertToBitmap() const
+{
+    wxBitmap bitmap;
+
+    wxCHECK_MSG( Ok(), bitmap, "invalid image" );
+
+    int width = GetWidth();
+    int height = GetHeight();
+
+    bitmap.SetHeight( height );
+    bitmap.SetWidth( width );
+
+    // Create picture
+
+    GdkImage *data_image =
+      gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), width, height );
+
+    bitmap.SetPixmap( gdk_pixmap_new( (GdkWindow*)&gdk_root_parent, width, height, -1 ) );
+
+    // Create mask
+
+    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 );
+    }
+
+    // Retrieve depth
+
+    GdkVisual *visual = gdk_window_get_visual( bitmap.GetPixmap() );
+    if (visual == NULL) visual = gdk_window_get_visual( (GdkWindow*) &gdk_root_parent );
+    int bpp = visual->depth;
+    
+    bitmap.SetDepth( bpp );
+    
+    if ((bpp == 16) && (visual->red_mask != 0xf800)) bpp = 15;
+    if (bpp < 8) bpp = 8;
+
+    // Render
+
+    enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
+    byte_order b_o = RGB;
+
+    if (bpp >= 24)
+    {
+        GdkVisual *visual = gdk_visual_get_system();
+        if ((visual->red_mask > visual->green_mask) && (visual->green_mask > visual->blue_mask))      b_o = RGB;
+        else if ((visual->red_mask > visual->blue_mask) && (visual->blue_mask > visual->green_mask))  b_o = RGB;
+        else if ((visual->blue_mask > visual->red_mask) && (visual->red_mask > visual->green_mask))   b_o = BRG;
+        else if ((visual->blue_mask > visual->green_mask) && (visual->green_mask > visual->red_mask)) b_o = BGR;
+        else if ((visual->green_mask > visual->red_mask) && (visual->red_mask > visual->blue_mask))   b_o = GRB;
+        else if ((visual->green_mask > visual->blue_mask) && (visual->blue_mask > visual->red_mask))  b_o = GBR;
+    }
+
+    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 );
+           }
+
+           switch (bpp)
+           {
+               case 8:
+               {
+                   GdkColormap *cmap = gtk_widget_get_default_colormap();
+                    GdkColor *colors = cmap->colors;
+                    int max = 3 * (65536);
+                    int index = -1;
+
+                    for (int i = 0; i < cmap->size; i++)
+                    {
+                        int rdiff = (r << 8) - colors[i].red;
+                        int gdiff = (g << 8) - colors[i].green;
+                        int bdiff = (b << 8) - colors[i].blue;
+                        int sum = ABS (rdiff) + ABS (gdiff) + ABS (bdiff);
+                        if (sum < max) { index = i; max = sum; }
+                    }
+
+                   gdk_image_put_pixel( data_image, x, y, index );
+
+                   break;
+               }
+               case 15:
+               {
+                   guint32 pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
+                   gdk_image_put_pixel( data_image, x, y, pixel );
+                   break;
+               }
+               case 16:
+               {
+                   guint32 pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
+                   gdk_image_put_pixel( data_image, x, y, pixel );
+                   break;
+               }
+               case 32:
+               case 24:
+               {
+                   guint32 pixel = 0;
+                   switch (b_o)
+                   {
+                       case RGB: pixel = (r << 16) | (g << 8) | b; break;
+                       case RBG: pixel = (r << 16) | (b << 8) | g; break;
+                       case BRG: pixel = (b << 16) | (r << 8) | g; break;
+                       case BGR: pixel = (b << 16) | (g << 8) | r; break;
+                       case GRB: pixel = (g << 16) | (r << 8) | b; break;
+                       case GBR: pixel = (g << 16) | (b << 8) | r; break;
+                   }
+                   gdk_image_put_pixel( data_image, x, y, pixel );
+               }
+               default: break;
+           }
+        } // for
+    }  // for
+
+    // Blit picture
+
+    GdkGC *data_gc = gdk_gc_new( bitmap.GetPixmap() );
+
+    gdk_draw_image( bitmap.GetPixmap(), 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;
+}
+
+wxImage::wxImage( const wxBitmap &bitmap )
+{
+    wxCHECK_RET( bitmap.Ok(), "invalid bitmap" );
+
+    GdkImage *gdk_image = gdk_image_get( bitmap.GetPixmap(),
+                                         0, 0,
+                                        bitmap.GetWidth(), bitmap.GetHeight() );
+
+    wxCHECK_RET( gdk_image, "couldn't create image" );
+
+    Create( bitmap.GetWidth(), bitmap.GetHeight() );
+    char unsigned *data = GetData();
+
+    if (!data)
+    {
+        gdk_image_destroy( gdk_image );
+        wxFAIL_MSG( "couldn't create image" );
+       return;
+    }
+
+    GdkImage *gdk_image_mask = (GdkImage*) NULL;
+    if (bitmap.GetMask())
+    {
+        gdk_image_mask = gdk_image_get( bitmap.GetMask()->GetBitmap(),
+                                       0, 0,
+                                       bitmap.GetWidth(), bitmap.GetHeight() );
+
+       SetMaskColour( 16, 16, 16 );  // anything unlikely and dividable
+    }
+
+    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;
+
+    GdkColormap *cmap = gtk_widget_get_default_colormap();
+
+    long pos = 0;
+    for (int j = 0; j < bitmap.GetHeight(); j++)
+    {
+        for (int i = 0; i < bitmap.GetWidth(); i++)
+        {
+            int 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)
+            {
+                data[pos] = (pixel >> 7) & 0xf8;
+                data[pos+1] = (pixel >> 2) & 0xf8;
+                data[pos+2] = (pixel << 3) & 0xf8;
+            } else if (bpp == 16)
+            {
+                data[pos] = (pixel >> 8) & 0xf8;
+                data[pos+1] = (pixel >> 3) & 0xfc;
+                data[pos+2] = (pixel << 3) & 0xf8;
+            } else
+            {
+                data[pos] = (pixel >> 16) & 0xff;
+                data[pos+1] = (pixel >> 8) & 0xff;
+                data[pos+2] = pixel & 0xff;
+            }
+
+           if (gdk_image_mask)
+           {
+               int mask_pixel = gdk_image_get_pixel( gdk_image_mask, i, j );
+               if (mask_pixel == 0)
+               {
+                    data[pos] = 16;
+                    data[pos+1] = 16;
+                    data[pos+2] = 16;
+              }
+           }
+
+            pos += 3;
+        }
+    }
+
+    gdk_image_destroy( gdk_image );
+    if (gdk_image_mask) gdk_image_destroy( gdk_image_mask );
+}
+
+#endif