]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/image.cpp
MIME classes with docs (not yet added to the makefiles)
[wxWidgets.git] / src / common / image.cpp
index 1e47bc22c7042076fdade1c6a0f2144c55d7dceb..ab13cbfbd4f8ef5f527a60871c995a9a92bfe289 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"
 
 //-----------------------------------------------------------------------------
@@ -153,6 +156,64 @@ wxImage wxImage::Scale( int width, int height )
     return image;
 }
   
+void wxImage::SetRGB( int x, int y, unsigned char r, unsigned char g, unsigned char b )
+{
+    wxCHECK_RET( Ok(), "invalid image" );
+    
+    int w = M_IMGDATA->m_width;
+    int h = M_IMGDATA->m_height;
+    
+    wxCHECK_RET( (x>=0) && (y>=0) && (x<w) && (y<h), "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 )
+{
+    wxCHECK_MSG( Ok(), 0, "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, "invalid image index" );
+    
+    long pos = (y * w + x) * 3;
+    
+    return M_IMGDATA->m_data[pos];
+}
+
+unsigned char wxImage::GetGreen( int x, int y )
+{
+    wxCHECK_MSG( Ok(), 0, "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, "invalid image index" );
+    
+    long pos = (y * w + x) * 3;
+    
+    return M_IMGDATA->m_data[pos+1];
+}
+
+unsigned char wxImage::GetBlue( int x, int y )
+{
+    wxCHECK_MSG( Ok(), 0, "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, "invalid image index" );
+    
+    long pos = (y * w + x) * 3;
+    
+    return M_IMGDATA->m_data[pos+2];
+}
+  
 bool wxImage::Ok() const 
 { 
     return (M_IMGDATA && M_IMGDATA->m_ok); 
@@ -333,7 +394,9 @@ wxImageHandler *wxImage::FindHandler( long bitmapType )
 void wxImage::InitStandardHandlers()
 {
     AddHandler( new wxBMPHandler );
+#ifdef wxUSE_LIBPNG
     AddHandler( new wxPNGHandler );
+#endif
 }
 
 void wxImage::CleanUpHandlers()
@@ -371,6 +434,8 @@ bool wxImageHandler::SaveFile( wxImage *WXUNUSED(image), const wxString& WXUNUSE
 // wxPNGHandler
 //-----------------------------------------------------------------------------
 
+#ifdef wxUSE_LIBPNG
+
 #if !USE_SHARED_LIBRARIES
 IMPLEMENT_DYNAMIC_CLASS(wxPNGHandler,wxImageHandler)
 #endif
@@ -596,6 +661,10 @@ bool wxPNGHandler::SaveFile( wxImage *image, const wxString& name )
   return TRUE;
 }
 
+#endif 
+
+  // wxUSE_LIBPNG
+
 //-----------------------------------------------------------------------------
 // wxBMPHandler
 //-----------------------------------------------------------------------------
@@ -610,7 +679,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    unsigned char      *data, *ptr;
    int                 done, i, bpp, planes, comp, ncolors, line, column,
                        linesize, linepos, rshift = 0, gshift = 0, bshift = 0;
-   unsigned char       byte;
+   unsigned char       aByte;
    short int           word;
    long int            dbuf[4], dword, rmask = 0, gmask = 0, bmask = 0, offset,
                        size;
@@ -624,6 +693,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
 
@@ -804,14 +876,14 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
                  int                 index;
 
                  linepos++;
-                 byte = getc(file);
+                 aByte = getc(file);
                  if (bpp == 1)
                    {
                       int                 bit = 0;
 
                       for (bit = 0; bit < 8; bit++)
                         {
-                           index = ((byte & (0x80 >> bit)) ? 1 : 0);
+                           index = ((aByte & (0x80 >> bit)) ? 1 : 0);
                            ptr[poffset] = cmap[index].r;
                            ptr[poffset + 1] = cmap[index].g;
                            ptr[poffset + 2] = cmap[index].b;
@@ -833,7 +905,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
 
                            for (nibble = 0; nibble < 2; nibble++)
                              {
-                                index = ((byte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
+                                index = ((aByte & (0xF0 >> nibble * 4)) >> (!nibble * 4));
                                 if (index >= 16)
                                    index = 15;
                                 ptr[poffset] = cmap[index].r;
@@ -849,51 +921,51 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
                         {
                            unsigned char       first;
 
-                           first = byte;
-                           byte = getc(file);
+                           first = aByte;
+                           aByte = getc(file);
                            if (first == 0)
                              {
-                                if (byte == 0)
+                                if (aByte == 0)
                                   {
 /*                                    column = width; */
                                   }
-                                else if (byte == 1)
+                                else if (aByte == 1)
                                   {
                                      column = width;
                                      line = -1;
                                   }
-                                else if (byte == 2)
+                                else if (aByte == 2)
                                   {
-                                     byte = getc(file);
-                                     column += byte;
+                                     aByte = getc(file);
+                                     column += aByte;
                                      linepos = column * bpp / 8;
-                                     byte = getc(file);
-                                     line += byte;
+                                     aByte = getc(file);
+                                     line += aByte;
                                   }
                                 else
                                   {
-                                     int                 absolute = byte;
+                                     int                 absolute = aByte;
 
                                      for (i = 0; i < absolute; i++)
                                        {
                                           linepos++;
-                                          byte = getc(file);
-                                          ptr[poffset] = cmap[byte].r;
-                                          ptr[poffset + 1] = cmap[byte].g;
-                                          ptr[poffset + 2] = cmap[byte].b;
+                                          aByte = getc(file);
+                                          ptr[poffset] = cmap[aByte].r;
+                                          ptr[poffset + 1] = cmap[aByte].g;
+                                          ptr[poffset + 2] = cmap[aByte].b;
                                           column++;
                                        }
                                      if (absolute & 0x01)
-                                        byte = getc(file);
+                                        aByte = getc(file);
                                   }
                              }
                            else
                              {
                                 for (i = 0; i < first; i++)
                                   {
-                                     ptr[poffset] = cmap[byte].r;
-                                     ptr[poffset + 1] = cmap[byte].g;
-                                     ptr[poffset + 2] = cmap[byte].b;
+                                     ptr[poffset] = cmap[aByte].r;
+                                     ptr[poffset + 1] = cmap[aByte].g;
+                                     ptr[poffset + 2] = cmap[aByte].b;
                                      column++;
                                      linepos++;
                                   }
@@ -901,9 +973,9 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
                         }
                       else
                         {
-                           ptr[poffset] = cmap[byte].r;
-                           ptr[poffset + 1] = cmap[byte].g;
-                           ptr[poffset + 2] = cmap[byte].b;
+                           ptr[poffset] = cmap[aByte].r;
+                           ptr[poffset + 1] = cmap[aByte].g;
+                           ptr[poffset + 2] = cmap[aByte].b;
                            column++;
                            linepos += size;
                         }
@@ -946,7 +1018,7 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
          }
        while ((linepos < linesize) && (comp != 1) && (comp != 2))
          {
-            int                 temp = fread(&byte, 1, 1, file);
+            int                 temp = fread(&aByte, 1, 1, file);
 
             linepos += temp;
             if (!temp)
@@ -961,3 +1033,474 @@ bool wxBMPHandler::LoadFile( wxImage *image, const wxString& name )
    return TRUE;
 }
 
+#ifdef __WXMSW__
+
+wxBitmap wxImage::ConvertToBitmap() const
+{
+  
+  wxBitmap bitmap;
+  wxCHECK_MSG( Ok(), bitmap, "invalid image" );
+  int width = GetWidth();
+  int height = GetHeight();
+  bitmap.SetWidth( width );
+  bitmap.SetHeight( height );
+  bitmap.SetDepth( wxDisplayDepth() );
+
+  int headersize = sizeof(BITMAPINFOHEADER);
+  LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
+  wxCHECK_MSG( lpDIBh, bitmap, "could not allocate memory for DIB header" );
+
+// Fill in the DIB header
+  lpDIBh->bmiHeader.biSize = headersize;
+  lpDIBh->bmiHeader.biWidth = width;
+  lpDIBh->bmiHeader.biHeight = -height;
+  lpDIBh->bmiHeader.biSizeImage = width * height * 3;
+
+  lpDIBh->bmiHeader.biPlanes = 1;
+  lpDIBh->bmiHeader.biBitCount = 24;
+  lpDIBh->bmiHeader.biCompression = BI_RGB;
+  lpDIBh->bmiHeader.biClrUsed = 0;
+
+// These seem not needed for our purpose here.
+//  lpDIBh->bmiHeader.biClrImportant = 0;
+//  lpDIBh->bmiHeader.biXPelsPerMeter = 0;
+//  lpDIBh->bmiHeader.biYPelsPerMeter = 0;
+
+  unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
+  if( !lpBits )
+  {
+      wxFAIL_MSG( "could not allocate memory for DIB" );
+      free( lpDIBh );
+      return bitmap;
+  }
+
+  unsigned char *data = GetData();
+
+  unsigned char *ptdata = data, *ptbits = lpBits;
+  for( int i=0; i<width*height; i++ )
+  {
+    *(ptbits++) = *(ptdata+2);
+    *(ptbits++) = *(ptdata+1);
+    *(ptbits++) = *(ptdata  );
+    ptdata += 3;
+  }
+  HDC hdc = ::GetDC(NULL);
+
+  HBITMAP hbitmap;
+  hbitmap = CreateDIBitmap( hdc, &(lpDIBh->bmiHeader), CBM_INIT, lpBits, lpDIBh, DIB_RGB_COLORS );
+    
+// The above line is equivalent to the following two lines.
+//    hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
+//    ::SetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS);
+// or the following lines
+//    hbitmap = ::CreateCompatibleBitmap( hdc, width, height );
+//    HDC memdc = ::CreateCompatibleDC( hdc );
+//    ::SelectObject( memdc, hbitmap); 
+//    ::SetDIBitsToDevice( memdc, 0, 0, width, height,
+//         0, 0, 0, height, (void *)lpBits, lpDIBh, DIB_RGB_COLORS);
+//    ::SelectObject( memdc, 0 ); 
+//    ::DeleteDC( memdc ); 
+
+  bitmap.SetHBITMAP( (WXHBITMAP) hbitmap );
+
+  if( HasMask() )
+  {
+    unsigned char r = GetMaskRed();
+    unsigned char g = GetMaskGreen();
+    unsigned char b = GetMaskBlue();
+    unsigned char zero = 0, one = 255;
+    ptdata = data;
+    ptbits = lpBits;
+    for( int i=0; i<width*height; i++ )
+    {
+      if( (*(ptdata++)!=r) | (*(ptdata++)!=g) | (*(ptdata++)!=b) )
+      {
+        *(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 *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 *mask = new wxMask( bitmap, colour );
+    bitmap.SetMask( mask );
+*/
+  }
+
+  ::ReleaseDC(NULL, hdc);   
+  free(lpDIBh);
+  free(lpBits);
+
+  if( bitmap.GetHBITMAP() )
+    bitmap.SetOk( TRUE );
+  else
+    bitmap.SetOk( FALSE );
+   
+  return bitmap;
+}
+
+
+wxImage::wxImage( const wxBitmap &bitmap )
+{
+  if( !bitmap.Ok() )
+  {
+      wxFAIL_MSG( "invalid bitmap" );
+      return;
+  }
+
+  int width = bitmap.GetWidth();
+  int height = bitmap.GetHeight();
+  Create( width, height ); 
+  unsigned char *data = GetData();
+  if( !data )
+  {
+      wxFAIL_MSG( "could not allocate data for image" );
+      return;
+  }
+    
+  int headersize = sizeof(BITMAPINFOHEADER);
+  LPBITMAPINFO lpDIBh = (BITMAPINFO *) malloc( headersize );
+  if( !lpDIBh )
+  {
+      wxFAIL_MSG( "could not allocate data for DIB header" );
+      free( data );
+      return;
+  }
+
+// Fill in the DIB header
+  lpDIBh->bmiHeader.biSize = headersize;
+  lpDIBh->bmiHeader.biWidth = width;
+  lpDIBh->bmiHeader.biHeight = -height;
+  lpDIBh->bmiHeader.biSizeImage = width * height * 3;
+
+  lpDIBh->bmiHeader.biPlanes = 1;
+  lpDIBh->bmiHeader.biBitCount = 24;
+  lpDIBh->bmiHeader.biCompression = BI_RGB;
+  lpDIBh->bmiHeader.biClrUsed = 0;
+
+// These seem not needed for our purpose here.
+//    lpDIBh->bmiHeader.biClrImportant = 0;
+//    lpDIBh->bmiHeader.biXPelsPerMeter = 0;
+//    lpDIBh->bmiHeader.biYPelsPerMeter = 0;
+
+  unsigned char *lpBits = (unsigned char *) malloc( width*height*3 );
+  if( !lpBits )
+  {
+      wxFAIL_MSG( "could not allocate data for DIB" );
+      free( data );
+      free( lpDIBh );
+      return;
+  }
+    
+  HBITMAP hbitmap;
+  hbitmap = (HBITMAP) bitmap.GetHBITMAP();
+  HDC hdc = ::GetDC(NULL);
+  ::GetDIBits( hdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
+       
+  unsigned char *ptdata = data, *ptbits = lpBits;
+  for( int i=0; i<width*height; i++ )
+  {
+    *(ptdata++) = *(ptbits+2);
+    *(ptdata++) = *(ptbits+1);
+    *(ptdata++) = *(ptbits  );
+    ptbits += 3;
+  }    
+      
+  if( bitmap.GetMask() && bitmap.GetMask()->GetMaskBitmap() )
+  {
+    hbitmap = (HBITMAP) bitmap.GetMask()->GetMaskBitmap();
+    HDC memdc = ::CreateCompatibleDC( hdc );
+    ::SetTextColor( memdc, RGB( 0, 0, 0 ) );
+    ::SetBkColor( memdc, RGB( 255, 255, 255 ) );
+    ::GetDIBits( memdc, hbitmap, 0, height, lpBits, lpDIBh, DIB_RGB_COLORS );
+    ::DeleteDC( memdc ); 
+    unsigned char r=16, g=16, b=16;  // background set to RGB(16,16,16)
+    ptdata = data;
+    ptbits = lpBits;
+    for( int i=0; i<width*height; i++ )
+    {
+      if( *ptbits != 0 )
+      {
+        *(ptdata++)  = r;
+        *(ptdata++)  = g;
+        *(ptdata++)  = b;
+      }
+      ptbits += 3;
+    }       
+    SetMaskColour( r, g, b );
+  }    
+      
+  ::ReleaseDC(NULL, hdc);   
+  free(lpDIBh);
+  free(lpBits);
+}
+
+#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;
+    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