gdip-pixbuf-loader r34 - in trunk: . src



Author: doml
Date: Sun Feb 24 22:42:26 2008
New Revision: 34
URL: http://svn.gnome.org/viewvc/gdip-pixbuf-loader?rev=34&view=rev

Log:
2008-02-24  Dom Lachowicz <domlachowicz gmail com>

	* src/*.c: Change to GTK+-style indentation; stub out some stuff for animation support

Modified:
   trunk/ChangeLog
   trunk/src/Makefile.test
   trunk/src/io-gdip-bmp.c
   trunk/src/io-gdip-gif.c
   trunk/src/io-gdip-jpeg.c
   trunk/src/io-gdip-png.c
   trunk/src/io-gdip-tiff.c
   trunk/src/io-gdip-utils.c
   trunk/src/io-gdip-utils.h
   trunk/src/io-gdip.c

Modified: trunk/src/Makefile.test
==============================================================================
--- trunk/src/Makefile.test	(original)
+++ trunk/src/Makefile.test	Sun Feb 24 22:42:26 2008
@@ -2,7 +2,8 @@
 CP=cp.exe
 
 PREFIX=/c/Program\ Files/Common\ Files/GTK/2.0
-CFLAGS=-I$(PREFIX)/include/glib-2.0/ -I$(PREFIX)/include/gtk-2.0 -I$(PREFIX)/include/pango-1.0 -I$(PREFIX)/lib/glib-2.0/include/
+LOADER_DIR=$(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+CFLAGS=-I$(PREFIX)/include/glib-2.0 -I$(PREFIX)/include/gtk-2.0 -I$(PREFIX)/include/pango-1.0 -I$(PREFIX)/lib/glib-2.0/include
 LDFLAGS=-L$(PREFIX)/lib/
 
 all: libpixbufloader-gdip-bmp.dll libpixbufloader-gdip-gif.dll libpixbufloader-gdip-jpeg.dll libpixbufloader-gdip-png.dll libpixbufloader-gdip-tiff.dll libpixbufloader-gdip.dll 
@@ -18,24 +19,24 @@
 
 libpixbufloader-gdip.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+	$(CP) $@ $(LOADER_DIR)
 
 libpixbufloader-gdip-bmp.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip-bmp.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip-bmp.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+	$(CP) $@ $(LOADER_DIR)
 
 libpixbufloader-gdip-gif.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip-gif.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip-gif.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+	$(CP) $@ $(LOADER_DIR)
 
 libpixbufloader-gdip-jpeg.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip-jpeg.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip-jpeg.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+	$(CP) $@ $(LOADER_DIR)
 
 libpixbufloader-gdip-png.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip-png.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip-png.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
+	$(CP) $@ $(LOADER_DIR)
 
 libpixbufloader-gdip-tiff.dll: io-gdip-native.h  io-gdip-utils.c  io-gdip-utils.h  io-gdip-tiff.c  Makefile.test
 	$(CC) -Wall -O0 -g -shared io-gdip-utils.c io-gdip-tiff.c $(CFLAGS) $(LDFLAGS) -lole32 -lglib-2.0 -lgobject-2.0 -lgdk_pixbuf-2.0 -o $@
-	$(CP) $@ $(PREFIX)/lib/gtk-2.0/2.10.0/loaders
\ No newline at end of file
+	$(CP) $@ $(LOADER_DIR)
\ No newline at end of file

Modified: trunk/src/io-gdip-bmp.c
==============================================================================
--- trunk/src/io-gdip-bmp.c	(original)
+++ trunk/src/io-gdip-bmp.c	Sun Feb 24 22:42:26 2008
@@ -48,20 +48,20 @@
                                  gchar        **values,
                                  GError       **error)
 {
-  return gdk_pixbuf__gdip_image_save_BMP_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+  return gdk_pixbuf__gdip_image_save_BMP_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
 }
 
 void
-MODULE_ENTRY(bmp, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (bmp, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 
   module->save_to_callback = gdk_pixbuf__gdip_image_save_BMP_to_callback;
   module->save = gdk_pixbuf__gdip_image_save_BMP; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
 }
 
 void
-MODULE_ENTRY(bmp, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (bmp, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "BM", NULL, 100 }, /* BMP */
@@ -82,7 +82,7 @@
 
   info->name        = "bmp";
   info->signature   = signature;
-  info->description = "Win32 GDI+ BMP loader.";
+  info->description = _("The BMP image format");
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;

Modified: trunk/src/io-gdip-gif.c
==============================================================================
--- trunk/src/io-gdip-gif.c	(original)
+++ trunk/src/io-gdip-gif.c	Sun Feb 24 22:42:26 2008
@@ -49,20 +49,20 @@
                                  gchar        **values,
                                  GError       **error)
 {
-  return gdk_pixbuf__gdip_image_save_GIF_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+  return gdk_pixbuf__gdip_image_save_GIF_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
 }
 
 void
-MODULE_ENTRY(gif, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (gif, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 
   module->save_to_callback = gdk_pixbuf__gdip_image_save_GIF_to_callback;
   module->save = gdk_pixbuf__gdip_image_save_GIF; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
 }
 
 void
-MODULE_ENTRY(gif, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (gif, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "GIF8", NULL, 100 }, /* GIF */
@@ -81,7 +81,7 @@
 
   info->name        = "gif";
   info->signature   = signature;
-  info->description = "Win32 GDI+ GIF loader.";
+  info->description = _("The GIF image format");
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;

Modified: trunk/src/io-gdip-jpeg.c
==============================================================================
--- trunk/src/io-gdip-jpeg.c	(original)
+++ trunk/src/io-gdip-jpeg.c	Sun Feb 24 22:42:26 2008
@@ -48,20 +48,20 @@
                                  gchar        **values,
                                  GError       **error)
 {
-  return gdk_pixbuf__gdip_image_save_JPEG_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+  return gdk_pixbuf__gdip_image_save_JPEG_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
 }
 
 void
-MODULE_ENTRY(jpeg, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (jpeg, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 
   module->save_to_callback = gdk_pixbuf__gdip_image_save_JPEG_to_callback;
   module->save = gdk_pixbuf__gdip_image_save_JPEG; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
 }
 
 void
-MODULE_ENTRY(jpeg, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (jpeg, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "\xff\xd8", NULL, 100 }, /* JPEG */
@@ -82,7 +82,7 @@
 
   info->name        = "jpeg";
   info->signature   = signature;
-  info->description = "Win32 GDI+ JPEG loader.";
+  info->description = _("The JPEG image format");
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;

Modified: trunk/src/io-gdip-png.c
==============================================================================
--- trunk/src/io-gdip-png.c	(original)
+++ trunk/src/io-gdip-png.c	Sun Feb 24 22:42:26 2008
@@ -49,20 +49,20 @@
                                  gchar        **values,
                                  GError       **error)
 {
-  return gdk_pixbuf__gdip_image_save_PNG_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+  return gdk_pixbuf__gdip_image_save_PNG_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
 }
 
 void
-MODULE_ENTRY(png, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (png, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 
   module->save_to_callback = gdk_pixbuf__gdip_image_save_PNG_to_callback;
   module->save = gdk_pixbuf__gdip_image_save_PNG; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
 }
 
 void
-MODULE_ENTRY(png, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (png, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "\x89PNG\r\n\x1a\x0a", NULL, 100 }, /* PNG */
@@ -81,7 +81,7 @@
 
   info->name        = "png";
   info->signature   = signature;
-  info->description = "Win32 GDI+ PNG loader.";
+  info->description = _("The PNG image format");
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;

Modified: trunk/src/io-gdip-tiff.c
==============================================================================
--- trunk/src/io-gdip-tiff.c	(original)
+++ trunk/src/io-gdip-tiff.c	Sun Feb 24 22:42:26 2008
@@ -49,20 +49,20 @@
                                  gchar        **values,
                                  GError       **error)
 {
-  return gdk_pixbuf__gdip_image_save_TIFF_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+  return gdk_pixbuf__gdip_image_save_TIFF_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
 }
 
 void
-MODULE_ENTRY(tiff, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (tiff, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 
   module->save_to_callback = gdk_pixbuf__gdip_image_save_TIFF_to_callback;
   module->save = gdk_pixbuf__gdip_image_save_TIFF; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
 }
 
 void
-MODULE_ENTRY(tiff, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (tiff, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "MM \x2a", "  z ", 100 }, /* TIFF */
@@ -83,7 +83,7 @@
 
   info->name        = "tiff";
   info->signature   = signature;
-  info->description = "Win32 GDI+ TIFF loader.";
+  info->description = "The TIFF image format";
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;

Modified: trunk/src/io-gdip-utils.c
==============================================================================
--- trunk/src/io-gdip-utils.c	(original)
+++ trunk/src/io-gdip-utils.c	Sun Feb 24 22:42:26 2008
@@ -28,6 +28,8 @@
 #include "io-gdip-native.h"
 #include "io-gdip-propertytags.h"
 
+#define LOAD_BUFFER_SIZE 65536
+
 static GdiplusStartupFunc GdiplusStartup;
 static GdipCreateBitmapFromStreamFunc GdipCreateBitmapFromStream;
 static GdipBitmapGetPixelFunc GdipBitmapGetPixel;
@@ -52,7 +54,18 @@
 DEFINE_GUID(FrameDimensionTime, 0x6aedbd6d,0x3fb5,0x418a,0x83,0xa6,0x7f,0x45,0x22,0x9d,0xc8,0x72);
 DEFINE_GUID(FrameDimensionPage, 0x7462dc86,0x6180,0x4c7e,0x8e,0x3f,0xee,0x73,0x33,0xa7,0xa4,0x83);
 
-gboolean
+static void
+gdip_propegate_error (GError **err,
+                      const char *reason,
+                      gint code)
+{
+  if (err) {
+    *err = NULL;
+    g_set_error (err, GDK_PIXBUF_ERROR, code, reason);
+  }
+}
+
+static gboolean
 io_gdip_init (void)
 {
   GdiplusStartupInput input;
@@ -68,18 +81,18 @@
     return FALSE;
 
 #define LOOKUP(func) \
-  do { \
-    func = (func##Func) GetProcAddress(gdipluslib, #func); \
+  G_STMT_START { \
+    func = (func##Func) GetProcAddress (gdipluslib, #func); \
     if (!func) {\
-      g_warning("Couldn't load function: %s\n", #func); \
+      /* g_warning ("Couldn't load function: %s\n", #func); */ \
       return FALSE; \
     } \
-  } while (0)
+  } G_STMT_END
 
 #define TRY_LOOKUP(func) \
-  do { \
-    func = (func##Func) GetProcAddress(gdipluslib, #func); \
-  } while (0)
+  G_STMT_START { \
+    func = (func##Func) GetProcAddress (gdipluslib, #func); \
+  } G_STMT_END
 
   LOOKUP (GdiplusStartup);
   LOOKUP (GdipCreateBitmapFromStream);
@@ -111,71 +124,64 @@
 }
 
 static int 
-GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
+GetEncoderClsid (const WCHAR *format, CLSID *pClsid)
 {
-  if (GetImageEncodersSize && GetImageEncoders)
-    {
-      UINT num = 0;
-      UINT size = 0;
-      UINT j;
-  
-      ImageCodecInfo* pImageCodecInfo = NULL;
-  
-      GetImageEncodersSize(&num, &size);
-      if(size == 0)
-        return -1;
-  
-      pImageCodecInfo = (ImageCodecInfo*)(g_try_malloc(size));
-      if(pImageCodecInfo == NULL)
-        return -1;
-
-      GetImageEncoders(num, size, pImageCodecInfo);
-  
-      for (j = 0; j < num; ++j)
-        {
-          if(wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
-            {
-              *pClsid = pImageCodecInfo[j].Clsid;
-              g_free(pImageCodecInfo);
-              return j;
-            }    
-        }
-
-      g_free(pImageCodecInfo);
+  if (GetImageEncodersSize && GetImageEncoders) {
+    UINT num = 0;
+    UINT size = 0;
+    UINT j;
+    
+    ImageCodecInfo *pImageCodecInfo = NULL;
+    
+    GetImageEncodersSize (&num, &size);
+    if(size == 0)
       return -1;
-    }
-  else
-    {
-      size_t i;
-
-      /* encoder formats supported by GDI+ out of the box */
-      struct
-      {
-        const WCHAR* format;
-        CLSID clsid;
-      } format_and_clsid[] = {
-        { L"image/bmp",  { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
-        { L"image/gif",  { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
-        { L"image/jpeg", { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
-        { L"image/png",  { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
-        { L"image/tiff", { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } }
-      };
-
-      for (i = 0; i < G_N_ELEMENTS(format_and_clsid); i++)
-        {
-          if (wcscmp(format, format_and_clsid[i].format) == 0)
-            {
-              *pClsid = format_and_clsid[i].clsid;
-              return i;
-            }
-        }
-
+    
+    pImageCodecInfo = (ImageCodecInfo *)(g_try_malloc (size));
+    if(pImageCodecInfo == NULL)
       return -1;
+    
+    GetImageEncoders (num, size, pImageCodecInfo);
+    
+    for (j = 0; j < num; ++j) {
+      if(wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
+        *pClsid = pImageCodecInfo[j].Clsid;
+        g_free (pImageCodecInfo);
+        return j;
+      }
+    }
+    
+    g_free (pImageCodecInfo);
+    return -1;
+  }
+  else {
+    size_t i;
+    
+    /* encoder formats supported by GDI+ out of the box */
+    struct {
+      const WCHAR *format;
+      CLSID clsid;
+    } format_and_clsid[] = {
+      { L"image/bmp",  { 0x557cf400, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
+      { L"image/gif",  { 0x557cf402, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
+      { L"image/jpeg", { 0x557cf401, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
+      { L"image/png",  { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } },
+      { L"image/tiff", { 0x557cf405, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } } }
+    };
+    
+    for (i = 0; i < G_N_ELEMENTS (format_and_clsid); i++) {
+      if (wcscmp (format, format_and_clsid[i].format) == 0) {
+        *pClsid = format_and_clsid[i].clsid;
+        return i;
+      }
     }
+
+    return -1;
+  }
 }
 
 static HGLOBAL
-io_gdip_buffer_to_hglobal (const gchar * buffer, size_t size)
+io_gdip_buffer_to_hglobal (const gchar *buffer, size_t size)
 {
   HGLOBAL hg = NULL;
 
@@ -189,7 +195,7 @@
   return hg;
 }
 
-gboolean
+static gboolean
 io_gdip_save_bitmap_to_callback (GpBitmap *bitmap,
                                  const CLSID *format,
                                  const EncoderParameters *encoder_params,
@@ -203,49 +209,44 @@
   guint64 zero = 0;
 
   hr = CreateStreamOnHGlobal (NULL, TRUE, &streamOut);
-  if (!SUCCEEDED(hr))
-    {
-      gdip_propegate_error (error, "Couldn't save", GDK_PIXBUF_ERROR_FAILED);
-      return FALSE;
-    }
+  if (!SUCCEEDED (hr)) {
+    gdip_propegate_error (error, _("Couldn't save"), GDK_PIXBUF_ERROR_FAILED);
+    return FALSE;
+  }
 
-  if (0 != GdipSaveImageToStream((GpImage*)bitmap, streamOut, format, encoder_params))
-    {
-      gdip_propegate_error (error, "Couldn't save", GDK_PIXBUF_ERROR_FAILED);
-      IStream_Release(streamOut);
-      return FALSE;
-    }
+  if (0 != GdipSaveImageToStream ((GpImage *)bitmap, streamOut, format, encoder_params)) {
+    gdip_propegate_error (error, _("Couldn't save"), GDK_PIXBUF_ERROR_FAILED);
+    IStream_Release (streamOut);
+    return FALSE;
+  }
 
   /* seek back to the beginning of the stream */
-  if (!SUCCEEDED(IStream_Seek(streamOut, *(LARGE_INTEGER *)&zero, STREAM_SEEK_SET, NULL)))
-    {
-      IStream_Release(streamOut);
-      return FALSE;
-    }
-
-  for (;;)
-    {
-      char buffer[1024];
-      ULONG nread;
-
-      hr = IStream_Read(streamOut, buffer, sizeof(buffer), &nread);
-      if (!SUCCEEDED(hr))
-          break;
-      else if (0 == nread)
-        {
-          success = TRUE; /* EOF */
-          break;
-        }
-      else if (!(*save_func)(buffer, nread, error, user_data))
-        break;
-    }
+  if (!SUCCEEDED (IStream_Seek (streamOut, *(LARGE_INTEGER *)&zero, STREAM_SEEK_SET, NULL))) {
+    IStream_Release (streamOut);
+    return FALSE;
+  }
+  
+  for (;;) {
+    char buffer[LOAD_BUFFER_SIZE];
+    ULONG nread;
+    
+    hr = IStream_Read (streamOut, buffer, sizeof(buffer), &nread);
+    if (!SUCCEEDED (hr))
+      break;
+    else if (0 == nread) {
+      success = TRUE; /* EOF */
+      break;
+    }
+    else if (!(*save_func) (buffer, nread, error, user_data))
+      break;
+  }
+  
+  IStream_Release (streamOut);
   
-  IStream_Release(streamOut);
-
   return success;
 }                     
 
-GpBitmap *
+static GpBitmap *
 io_gdip_pixbuf_to_bitmap (GdkPixbuf *pixbuf)
 {
   GpBitmap *bitmap = NULL;
@@ -253,99 +254,58 @@
   int width, height, stride, n_channels;
   guint8 *pixels;
 
-  width = gdk_pixbuf_get_width(pixbuf);
-  height = gdk_pixbuf_get_height(pixbuf);
-  stride = gdk_pixbuf_get_rowstride(pixbuf);
-  n_channels = gdk_pixbuf_get_n_channels(pixbuf);
-  pixels = gdk_pixbuf_get_pixels(pixbuf);
-
-  if (n_channels == 3 || n_channels == 4)
-    {
-      /* rgbX. need to convert to argb */
-      GdipCreateBitmapFromScan0(width, height, stride, PixelFormat32bppARGB, NULL, &bitmap);
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+  stride = gdk_pixbuf_get_rowstride (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+  if (n_channels == 3 || n_channels == 4) {
+    /* rgbX. need to convert to argb. pass a null data to get an empty bitmap */
+    GdipCreateBitmapFromScan0 (width, height, stride, PixelFormat32bppARGB, NULL, &bitmap);
+    
+    if (bitmap) {
+      int x, y;
       
-      if (bitmap)
-        {
-          int x, y;
-
-          for (y = 0; y < height; y++)
-            {
-              for (x = 0; x < width; x++)
-                {
-                  ARGB p;
-                  guchar *base = pixels + (y * stride + (x * n_channels));
-                  guint8 alpha = 0xff;
-                  
-                  if (n_channels == 4)
-                    {
-                      alpha = base[3];
-                    }
-                  
-                  if (alpha == 0) 
-                    {
-                      p = 0;
-                    }
-                  else 
-                    {
-                      guint8 red = base[0];
-                      guint8 green = base[1];
-                      guint8 blue = base[2];
-                      
-                      p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
-                    }
+      for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++) {
+          ARGB p;
+          guint8 alpha;
+          guchar *base = pixels + (y * stride + (x * n_channels));
+          
+          if (n_channels == 4)
+            alpha = base[3];
+          else
+            alpha = 0xff;
                   
-                  GdipBitmapSetPixel(bitmap, x, y, p);
-                }
-            }
-        }
-    }
-  else
-    {
-      g_warning ("Unsupported number of channels: %d\n", n_channels);
-    }
-
+          if (alpha == 0) 
+            p = 0;
+          else {
+            guint8 red = base[0];
+            guint8 green = base[1];
+            guint8 blue = base[2];
+            
+            p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
+          }
+          
+          GdipBitmapSetPixel (bitmap, x, y, p);
+        }
+      }
+    }
+  }
+  else {
+    g_warning ("Unsupported number of channels: %d\n", n_channels);
+  }
+  
   return bitmap;
 }
 
-gboolean
-io_gdip_save_pixbuf (GdkPixbuf *pixbuf,
-                     const WCHAR *format,
-                     const EncoderParameters *encoder_params,
-                     GdkPixbufSaveFunc save_func,
-                     gpointer user_data,
-                     GError **error)
-{
-  GpBitmap *image;
-  CLSID clsid;
-  gboolean success;
-
-  if (-1 == GetEncoderClsid(format, &clsid))
-    {
-      gdip_propegate_error (error, "Unsupported format", GDK_PIXBUF_ERROR_FAILED);
-      return FALSE;
-    }
-
-  image = io_gdip_pixbuf_to_bitmap(pixbuf);
-
-  if (image == NULL)
-    {
-      gdip_propegate_error (error, "Couldn't save", GDK_PIXBUF_ERROR_FAILED);
-      return FALSE;
-    }
-
-  success = io_gdip_save_bitmap_to_callback(image, &clsid, encoder_params, save_func, user_data, error);
-
-  io_gdip_dispose_bitmap(image);
-
-  return success;
-}
-
-GpBitmap *
-io_gdip_buffer_to_bitmap (const gchar * buffer, size_t size)
+static GpBitmap *
+io_gdip_buffer_to_bitmap (const gchar *buffer, size_t size)
 {
   HRESULT hr;
   HGLOBAL hg = NULL;
-  GpBitmap * bitmap = NULL;
+  GpBitmap *bitmap = NULL;
   IStream *stream = NULL;
   int status;
 
@@ -354,65 +314,46 @@
   if (!hg)
     return NULL;
 
-  hr = CreateStreamOnHGlobal (hg, FALSE, (LPSTREAM*)&stream);
-
-  if (!SUCCEEDED(hr))
-    {
-      GlobalFree(hg);
-      return NULL;
-    }
+  hr = CreateStreamOnHGlobal (hg, FALSE, (LPSTREAM *)&stream);
 
-  status = GdipCreateBitmapFromStream(stream, &bitmap);
+  if (!SUCCEEDED (hr)) {
+    GlobalFree (hg);
+    return NULL;
+  }
+  
+  status = GdipCreateBitmapFromStream (stream, &bitmap);
 
-  IStream_Release(stream);
-  GlobalFree(hg);
+  IStream_Release (stream);
+  GlobalFree (hg);
 
   return bitmap;
 }
 
-gboolean
-io_gdip_bitmap_get_size (GpBitmap * bitmap, guint * width, guint * height)
+static void
+io_gdip_bitmap_get_size (GpBitmap *bitmap, guint *width, guint *height)
 {
   if (bitmap == NULL || width == NULL || height == NULL)
-    return FALSE;
+    return;
 
-  GdipGetImageWidth ((GpImage*) bitmap, width);
-  GdipGetImageHeight ((GpImage*) bitmap, height);
+  *width = *height = 0;
 
-  return TRUE;
+  GdipGetImageWidth ((GpImage *) bitmap, width);
+  GdipGetImageHeight ((GpImage *) bitmap, height);
 }
 
-gboolean
-io_gdip_bitmap_get_has_alpha (GpBitmap * bitmap, gboolean * has_alpha)
+static void
+io_gdip_bitmap_get_has_alpha (GpBitmap *bitmap, gboolean *has_alpha)
 {
   guint flags = 0;
 
   if (bitmap == NULL || has_alpha == NULL)
-    return FALSE;
+    return;
 
-  GdipGetImageFlags ((GpImage*) bitmap, &flags);
+  GdipGetImageFlags ((GpImage *) bitmap, &flags);
   *has_alpha = (flags & ImageFlagsHasAlpha);
-
-  return TRUE;
-}
-
-ARGB
-io_gdip_bitmap_get_pixel (GpBitmap *bitmap, guint x, guint y)
-{
-  ARGB pixel;
-
-  GdipBitmapGetPixel (bitmap, x, y, &pixel);
-
-  return pixel;
 }
 
-void
-io_gdip_dispose_bitmap (GpBitmap *bitmap)
-{
-  GdipDisposeImage ((GpImage*) bitmap);
-}
-
-gboolean
+static gboolean
 io_gdip_bitmap_get_n_frames (GpBitmap *bitmap, guint *n_frames, gboolean timeDimension)
 {
   if (bitmap == NULL || n_frames == NULL)
@@ -420,77 +361,19 @@
 
   *n_frames = 1;
 
-  return (0 == GdipImageGetFrameCount((GpImage*) bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), n_frames));
-}
-
-gboolean
-io_gdip_bitmap_get_frame_delay (GpBitmap *bitmap, guint *delay)
-{
-  guint item_size;
-  gboolean success = FALSE;
-
-  if (bitmap == NULL || delay == NULL)
-    return FALSE;
-
-  *delay = 0;
-
-  if (0 == GdipGetPropertyItemSize ((GpImage*)bitmap, PropertyTagFrameDelay, &item_size))
-    {
-      PropertyItem *item;
-
-      item = (PropertyItem *)g_try_malloc(item_size);
-      if (0 == GdipGetPropertyItem ((GpImage*)bitmap, PropertyTagFrameDelay, item_size, item))
-        {
-          /* PropertyTagFrameDelay. Time delay, in hundredths of a second, between two frames in an animated GIF image. */
-          *delay = *((long*)item->value);
-          success = TRUE;
-        }
-
-      g_free(item);
-    }
-
-  return success;
+  return (0 == GdipImageGetFrameCount ((GpImage *) bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), n_frames));
 }
 
-gboolean
+static gboolean
 io_gdip_bitmap_select_frame (GpBitmap *bitmap, guint frame, gboolean timeDimension)
 {
   if (bitmap == NULL)
     return FALSE;
 
-  return (0 == GdipImageSelectActiveFrame((GpImage*)bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), frame));
-}
-
-gboolean
-io_gdip_bitmap_get_n_loops (GpBitmap *bitmap, guint *loops)
-{
-  guint item_size;
-  gboolean success = FALSE;
-
-  if (bitmap == NULL || loops == NULL)
-    return FALSE;
-
-  *loops = 1;
-
-  /* PropertyTagLoopCount. 0 == infinitely */
-  if (0 == GdipGetPropertyItemSize ((GpImage*)bitmap, PropertyTagLoopCount, &item_size))
-    {
-      PropertyItem *item;
-
-      item = (PropertyItem *)g_try_malloc(item_size);
-      if (0 == GdipGetPropertyItem ((GpImage*)bitmap, PropertyTagLoopCount, item_size, item))
-        {
-          *loops = *((short*)item->value);
-          success = TRUE;
-        }
-
-      g_free(item);
-    }
-
-  return success;
+  return (0 == GdipImageSelectActiveFrame ((GpImage *)bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), frame));
 }
 
-gboolean
+static gboolean
 io_gdip_bitmap_get_property_as_string (GpBitmap *bitmap, guint propertyId, gchar **str)
 {
   guint item_size;
@@ -501,128 +384,118 @@
 
   *str = 0;
 
-  if (0 == GdipGetPropertyItemSize ((GpImage*)bitmap, propertyId, &item_size))
-    {
-      PropertyItem *item;
+  if (0 == GdipGetPropertyItemSize ((GpImage *)bitmap, propertyId, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (0 == GdipGetPropertyItem ((GpImage *)bitmap, propertyId, item_size, item)) {
+      GString *gstr;
+      int i;
       
-      item = (PropertyItem *)g_try_malloc(item_size);
-      if (0 == GdipGetPropertyItem ((GpImage*)bitmap, propertyId, item_size, item))
-        {
-          GString *gstr;
-          int i;
-
-          gstr = g_string_new(NULL);
-
-          success = TRUE;
-          switch (item->type)
-            {
-            case PropertyTagTypeByte:
-              for (i = 0; i < item->length / sizeof(guint8); i++)
-                {
-                  guint8 *bytes = (guint8*)item->value;
-
-                  if (gstr->len != 0)
-                    g_string_append_c(gstr, ',');
-                  g_string_append_printf(gstr, "%u", (guint32)bytes[i]);
-                }
-              break;
-
-            case PropertyTagTypeASCII:
-              g_string_append_len(gstr, (const char *)item->value, item->length);
-              break;
-
-            case PropertyTagTypeShort:
-              for (i = 0; i < item->length / sizeof(guint16); i++)
-                {
-                  guint16 *shorts = (guint16*)item->value;
-
-                  if (gstr->len != 0)
-                    g_string_append_c(gstr, ',');
-                  g_string_append_printf(gstr, "%u", (guint32)shorts[i]);
-                }
-              break;
-
-            case PropertyTagTypeLong:
-              for (i = 0; i < item->length / sizeof(guint32); i++)
-                {
-                  guint32 *longs = (guint32*)item->value;
-
-                  if (gstr->len != 0)
-                    g_string_append_c(gstr, ',');
-                  g_string_append_printf(gstr, "%u", longs[i]);
-                }
-              break;
-
-            case PropertyTagTypeSLONG:
-              for (i = 0; i < item->length / sizeof(guint32); i++)
-                {
-                  gint32 *longs = (gint32*)item->value;
-
-                  if (gstr->len != 0)
-                    g_string_append_c(gstr, ',');
-                  g_string_append_printf(gstr, "%d", longs[i]);
-                }
-              break;
-
-            default:
-              success = FALSE;
-              break;
-            }
-
-          if (gstr->len > 0)
-            *str = g_string_free(gstr, FALSE);
-          else
-            g_string_free(gstr, TRUE);
+      gstr = g_string_new (NULL);
+      
+      success = TRUE;
+      switch (item->type) {
+      case PropertyTagTypeByte:
+        for (i = 0; i < item->length / sizeof(guint8); i++) {
+          guint8 *bytes = (guint8 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c(gstr, ',');
+          g_string_append_printf (gstr, "%u", (guint32)bytes[i]);
         }
+        break;
+        
+      case PropertyTagTypeASCII:
+        g_string_append_len (gstr, (const char *)item->value, item->length);
+        break;
+        
+      case PropertyTagTypeShort:
+        for (i = 0; i < item->length / sizeof(guint16); i++) {
+          guint16 *shorts = (guint16 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%u", (guint32)shorts[i]);
+        }
+        break;
+        
+      case PropertyTagTypeLong:
+        for (i = 0; i < item->length / sizeof(guint32); i++) {
+          guint32 *longs = (guint32 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%u", longs[i]);
+        }
+        break;
 
-      g_free(item);
-    }
-
+      case PropertyTagTypeSLONG:
+        for (i = 0; i < item->length / sizeof(guint32); i++) {
+          gint32 *longs = (gint32 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%d", longs[i]);
+        }
+        break;
+        
+      default:
+        success = FALSE;
+        break;
+      }
+      
+      if (gstr->len > 0)
+        *str = g_string_free (gstr, FALSE);
+      else
+        g_string_free (gstr, TRUE);
+    }
+    
+    g_free (item);
+  }
+  
   return success;
 }
 
 /*************************************************************************/
 /*************************************************************************/
 
-struct _GdipContext{
+struct _GdipContext {
   GdkPixbufModuleUpdatedFunc  updated_func;
   GdkPixbufModulePreparedFunc prepared_func;
   GdkPixbufModuleSizeFunc     size_func;
 
-  gboolean                    first_write;
-
   gpointer                    user_data;
 
-  GByteArray*                 buffer;
+  GByteArray                 *buffer;
 };
 typedef struct _GdipContext GdipContext;
 
 static void
 destroy_gdipcontext (GdipContext *context)
 {
-  if (context != NULL)
-    {
-      g_byte_array_free (context->buffer, TRUE);
-      g_free (context);
-    }
+  if (context != NULL) {
+    g_byte_array_free (context->buffer, TRUE);
+    g_free (context);
+  }
 }
 
 static void
 emit_updated (GdipContext *context, GdkPixbuf *pixbuf)
 {
-  if (context->updated_func != NULL)
-    (* context->updated_func) (pixbuf,
-                               0, 0,
-                               gdk_pixbuf_get_width (pixbuf),
-                               gdk_pixbuf_get_height (pixbuf),
-                               context->user_data);
+  if (context->updated_func)
+    (*context->updated_func) (pixbuf,
+                              0, 0,
+                              gdk_pixbuf_get_width (pixbuf),
+                              gdk_pixbuf_get_height (pixbuf),
+                              context->user_data);
 }
 
 static void
 emit_prepared (GdipContext *context, GdkPixbuf *pixbuf, GdkPixbufAnimation *anim)
 {
-  if (context->prepared_func != NULL)
-    (* context->prepared_func) (pixbuf, anim, context->user_data);
+  if (context->prepared_func)
+    (*context->prepared_func) (pixbuf, anim, context->user_data);
 }
 
 static gpointer
@@ -632,25 +505,21 @@
                                    gpointer user_data,
                                    GError **error)
 {
-  GdipContext *context = g_new(GdipContext, 1);
+  GdipContext *context = g_try_new0 (GdipContext, 1);
 
-  if (!context)
-    {
-      gdip_propegate_error (error, "Couldn't create context", GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY);
-      return NULL;
-    }
+  if (!context) {
+    gdip_propegate_error (error, _("Couldn't create context"), GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY);
+    return NULL;
+  }
 
   if (error)
     *error = NULL;
 
-  context->first_write   = TRUE;
   context->size_func     = size_func;
-
   context->prepared_func = prepared_func;
   context->updated_func  = updated_func;
   context->user_data     = user_data;
-
-  context->buffer  = g_byte_array_new();
+  context->buffer        = g_byte_array_new ();
 
   return context;
 }
@@ -666,12 +535,12 @@
   if (error)
     *error = NULL;
 
-  g_byte_array_append(image_buffer, (guint8*)buf, size);
+  g_byte_array_append (image_buffer, (guint8 *)buf, size);
 
   return TRUE;
 }
 
-static GdkPixbuf*
+static GdkPixbuf *
 gdi_bitmap_to_pixbuf (GpBitmap *bitmap)
 {
   GdkPixbuf *pixbuf = NULL;
@@ -689,54 +558,42 @@
   pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, width, height);
 
   if (!pixbuf)
-    {
-      return NULL;
-    }
+    return NULL;
 
   rowstride = gdk_pixbuf_get_rowstride (pixbuf);
   cursor = gdk_pixbuf_get_pixels (pixbuf);
   n_channels = gdk_pixbuf_get_n_channels (pixbuf);
 
-  for (y = 0; y < height; y++)
-    {
-      for (x = 0; x < width; x++)
-        {
-          ARGB pixel;
-          guchar *b = cursor + (y * rowstride + (x * n_channels));
-
-          pixel = io_gdip_bitmap_get_pixel (bitmap, x, y);
-
-          b[0] = (pixel & 0xff0000) >> 16;
-          b[1] = (pixel & 0x00ff00) >> 8;
-          b[2] = (pixel & 0x0000ff) >> 0;
-
-          if (has_alpha)
-            {
-              b[3] = (pixel & 0xff000000) >> 24;
-            }
-        }
-    }
-
-  io_gdip_bitmap_get_property_as_string(bitmap, PropertyTagImageWidth, &option);
-  g_free(option);
-
-  if (io_gdip_bitmap_get_property_as_string(bitmap, PropertyTagOrientation, &option))
-    {
-      gdk_pixbuf_set_option (pixbuf, "orientation", option);
-      g_free(option);
-    }
-
-  if (io_gdip_bitmap_get_property_as_string(bitmap, PropertyTagArtist, &option))
-    {
-      gdk_pixbuf_set_option (pixbuf, "Author", option);
-      g_free(option);
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      ARGB pixel;
+      guchar *b = cursor + (y * rowstride + (x * n_channels));
+      
+      GdipBitmapGetPixel (bitmap, x, y, &pixel);
+      
+      b[0] = (pixel & 0xff0000) >> 16;
+      b[1] = (pixel & 0x00ff00) >> 8;
+      b[2] = (pixel & 0x0000ff) >> 0;
+      
+      if (has_alpha)      
+        b[3] = (pixel & 0xff000000) >> 24;
     }
+  }
 
-  if (io_gdip_bitmap_get_property_as_string(bitmap, PropertyTagImageTitle, &option))
-    {
-      gdk_pixbuf_set_option (pixbuf, "Title", option);
-      g_free(option);
-    }
+  if (io_gdip_bitmap_get_property_as_string (bitmap, PropertyTagOrientation, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "orientation", option);
+    g_free (option);
+  }
+
+  if (io_gdip_bitmap_get_property_as_string (bitmap, PropertyTagArtist, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "Author", option);
+    g_free (option);
+  }
+
+  if (io_gdip_bitmap_get_property_as_string (bitmap, PropertyTagImageTitle, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "Title", option);
+    g_free (option);
+  }
 
   return pixbuf;
 }
@@ -746,76 +603,163 @@
 {
   GdipContext *context = (GdipContext *)data;
   GpBitmap    *bitmap = NULL;
-
+  
   GByteArray *image_buffer = context->buffer;
   guint8     *tmp_buffer = NULL;
   guint       buffer_len = 0;
   guint       n_frames = 1, i;
 
-  GdkPixbufAnimation *anim = NULL;
-
   if (error)
     *error = NULL;
 
   buffer_len = image_buffer->len;
   tmp_buffer = image_buffer->data;
 
-  bitmap = io_gdip_buffer_to_bitmap ((gchar*)image_buffer->data, image_buffer->len);
+  bitmap = io_gdip_buffer_to_bitmap ((gchar *)image_buffer->data, image_buffer->len);
+
+  if (!bitmap) {
+    destroy_gdipcontext (context);
+    gdip_propegate_error (error, _("Couldn't load bitmap"), GDK_PIXBUF_ERROR_CORRUPT_IMAGE);
+    return FALSE;
+  }
+
+  io_gdip_bitmap_get_n_frames (bitmap, &n_frames, TRUE);
 
-  if (!bitmap)
-    {
+  for (i = 0; i < n_frames; i++) {
+    GdkPixbuf *pixbuf = NULL;
+    
+    io_gdip_bitmap_select_frame (bitmap, i, TRUE);
+    
+    pixbuf = gdi_bitmap_to_pixbuf (bitmap);
+    
+    if (!pixbuf) {
       destroy_gdipcontext (context);
-      gdip_propegate_error (error, "Couldn't load bitmap", GDK_PIXBUF_ERROR_CORRUPT_IMAGE);
+      gdip_propegate_error (error, _("Couldn't create pixbuf"), GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY);
       return FALSE;
     }
+    
+    if (i == 0)
+      emit_prepared (context, pixbuf, NULL);
+
+    emit_updated (context, pixbuf);
+
+    /* emit_prepared() takes a ref */
+    g_object_unref (G_OBJECT (pixbuf));
+  }
 
-  io_gdip_bitmap_get_n_frames (bitmap, &n_frames, TRUE);
+  destroy_gdipcontext (context);
+  
+  return TRUE;
+}
 
-  for (i = 0; i < n_frames; i++)
-    {
-      GdkPixbuf *pixbuf = NULL;
-
-      io_gdip_bitmap_select_frame (bitmap, i, TRUE);
-
-      if (n_frames > 1 && i == 0)
-        {
-          guint delay; /* in hundredths per second */
-          guint width = 0, height = 0;
-          gfloat rate = 1;
+#if 0
 
-          io_gdip_bitmap_get_frame_delay (bitmap, &delay);
-          rate = 1.0f / ((gfloat)delay / 100);
+static gboolean
+io_gdip_bitmap_get_frame_delay (GpBitmap *bitmap, guint *delay)
+{
+  guint item_size;
+  gboolean success = FALSE;
 
-          io_gdip_bitmap_get_size (bitmap, &width, &height);
-          /* anim = GDK_PIXBUF_ANIMATION(gdk_pixbuf_simple_anim_new (width, height, rate)); */
-        }
+  if (bitmap == NULL || delay == NULL)
+    return FALSE;
 
-      pixbuf = gdi_bitmap_to_pixbuf (bitmap);
+  *delay = 0;
 
-      if (!pixbuf)
-        {
-          destroy_gdipcontext (context);
-          gdip_propegate_error (error, "Couldn't create pixbuf", GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY);
-          return FALSE;
-        }
+  if (0 == GdipGetPropertyItemSize ((GpImage *)bitmap, PropertyTagFrameDelay, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (0 == GdipGetPropertyItem ((GpImage *)bitmap, PropertyTagFrameDelay, item_size, item)) {
+      /* PropertyTagFrameDelay. Time delay, in hundredths of a second, between two frames in an animated GIF image. */
+      *delay = *((long *)item->value);
+      success = TRUE;
+    }
+    
+    g_free (item);
+  }
+  
+  return success;
+}
 
-      if (anim != NULL)
-        {
-          gdk_pixbuf_simple_anim_add_frame (GDK_PIXBUF_SIMPLE_ANIM(anim), pixbuf);
-        }
+static gboolean
+io_gdip_bitmap_get_n_loops (GpBitmap *bitmap, guint *loops)
+{
+  guint item_size;
+  gboolean success = FALSE;
 
-      if (i == 0)
-        {
-          emit_prepared (context, pixbuf, anim);
-        }
+  if (bitmap == NULL || loops == NULL)
+    return FALSE;
 
-      emit_updated (context, pixbuf);
-    }
+  *loops = 1;
 
-  destroy_gdipcontext (context);
+  /* PropertyTagLoopCount. 0 == infinitely */
+  if (0 == GdipGetPropertyItemSize ((GpImage *)bitmap, PropertyTagLoopCount, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (0 == GdipGetPropertyItem ((GpImage *)bitmap, PropertyTagLoopCount, item_size, item)) {
+      *loops = *((short *)item->value);
+      success = TRUE;
+    }
+    
+    g_free (item);
+  }
+  
+  return success;
+}
 
-  return TRUE;
+static void 
+gdip_animation_prepare(GdkPixbuf *pixbuf,
+                       GdkPixbufAnimation *animation,
+                       gpointer user_data)
+{
+  GdkPixbufAnimation **anim;
+
+  anim = (GdkPixbufAnimation **)user_data;
+
+  /* save a reference to the animation */
+  g_object_ref (animation);
+  *anim = animation;
+}
+
+static GdkPixbufAnimation *
+gdk_pixbuf__gdip_image_load_animation (FILE *file,
+                                       GError **error)
+{
+  GdkPixbufAnimation *animation = NULL;
+
+  gpointer context;
+  char buffer[LOAD_BUFFER_SIZE];
+  size_t length;
+
+  context = gdk_pixbuf__gdip_image_begin_load (NULL, gdip_animation_prepare, NULL, &animation, error);
+  if (!context)
+      return NULL;
+
+  while (!feof (file) && !ferror (file)) {
+    length = fread (buffer, 1, sizeof (buffer), file);
+    if (length > 0) {
+      if (!gdk_pixbuf__gdip_image_load_increment (context, buffer, length, error)) {
+        gdk_pixbuf__gdip_image_stop_load (context, NULL);
+
+        if (animation)
+          g_object_unref (animation);
+
+        return NULL;
+      }
+    }
+  }
+
+  if (!gdk_pixbuf__gdip_image_stop_load(context, error)) {
+    if (animation)
+      g_object_unref (animation);
+    
+    return NULL;
+  }
+
+  return animation;
 }
+#endif
 
 gboolean
 gdip_save_to_file_callback (const gchar *buf,
@@ -823,41 +767,65 @@
                             GError     **error,
                             gpointer     data)
 {
-        FILE *filehandle = data;
-        gsize n;
-
-        n = fwrite (buf, 1, count, filehandle);
-        if (n != count) {
-                gint save_errno = errno;
-                g_set_error (error,
-                             G_FILE_ERROR,
-                             g_file_error_from_errno (save_errno),
-                             "Error writing to image file: %s",
-                             g_strerror (save_errno));
-                return FALSE;
-        }
-        return TRUE;
+  FILE *filehandle = data;
+  gsize n;
+  
+  n = fwrite (buf, 1, count, filehandle);
+  if (n != count) {
+    gint save_errno = errno;
+    g_set_error (error,
+                 G_FILE_ERROR,
+                 g_file_error_from_errno (save_errno),
+                 _("Error writing to image file: %s"),
+                 g_strerror (save_errno));
+    return FALSE;
+  }
+  
+  return TRUE;
 }
 
-/* meant to be shared across various GDI+ plugins, since we'll need multiple plugins to support saving to multiple formats */
 void
 gdip_fill_vtable (GdkPixbufModule *module)
 {
-  io_gdip_init ();
-
-  module->begin_load     = gdk_pixbuf__gdip_image_begin_load;
-  module->stop_load      = gdk_pixbuf__gdip_image_stop_load;
-  module->load_increment = gdk_pixbuf__gdip_image_load_increment;
+  if (io_gdip_init ()) {
+    module->begin_load     = gdk_pixbuf__gdip_image_begin_load;
+    module->stop_load      = gdk_pixbuf__gdip_image_stop_load;
+    module->load_increment = gdk_pixbuf__gdip_image_load_increment;
+    
+#if 0
+    /* this is the only way to get gtk_image_new_from_file() to load animations */
+    module->load_animation = gdk_pixbuf__gdip_image_load_animation;
+#endif
+  }
 }
 
-void
-gdip_propegate_error (GError ** err,
-                      const char * reason,
-                      gint code)
+gboolean
+io_gdip_save_pixbuf (GdkPixbuf *pixbuf,
+                     const WCHAR *format,
+                     const EncoderParameters *encoder_params,
+                     GdkPixbufSaveFunc save_func,
+                     gpointer user_data,
+                     GError **error)
 {
-  if (err)
-    {
-      *err = NULL;
-      g_set_error (err, GDK_PIXBUF_ERROR, code, reason);
-    }
+  GpBitmap *image;
+  CLSID clsid;
+  gboolean success;
+
+  if (-1 == GetEncoderClsid (format, &clsid)) {
+    gdip_propegate_error (error, _("Unsupported format"), GDK_PIXBUF_ERROR_FAILED);
+    return FALSE;
+  }
+  
+  image = io_gdip_pixbuf_to_bitmap (pixbuf);
+
+  if (image == NULL) {
+    gdip_propegate_error (error, _("Couldn't save"), GDK_PIXBUF_ERROR_FAILED);
+    return FALSE;
+  }
+  
+  success = io_gdip_save_bitmap_to_callback (image, &clsid, encoder_params, save_func, user_data, error);
+
+  GdipDisposeImage ((GpImage *)image);
+
+  return success;
 }

Modified: trunk/src/io-gdip-utils.h
==============================================================================
--- trunk/src/io-gdip-utils.h	(original)
+++ trunk/src/io-gdip-utils.h	Sun Feb 24 22:42:26 2008
@@ -27,6 +27,11 @@
 #define GDK_PIXBUF_ENABLE_BACKEND
 #include <gdk-pixbuf/gdk-pixbuf-io.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
+/* #include <glib/gi18n-lib.h> */
+
+#ifndef _
+#define _(x) (x)
+#endif
 
 #include "io-gdip-native.h"
 
@@ -45,52 +50,6 @@
 void
 gdip_fill_vtable (GdkPixbufModule *module);
 
-void
-gdip_propegate_error (GError ** err,
-                      const char * reason,
-                      gint code);
-
-gboolean 
-io_gdip_init (void);
-
-GpBitmap *
-io_gdip_buffer_to_bitmap (const gchar *, size_t);
-
-void
-io_gdip_dispose_bitmap (GpBitmap *);
-
-gboolean
-io_gdip_bitmap_get_size (GpBitmap *, guint *, guint *);
-
-gboolean
-io_gdip_bitmap_get_has_alpha (GpBitmap *, gboolean *);
-
-ARGB
-io_gdip_bitmap_get_pixel (GpBitmap *bitmap, guint x, guint y);
-
-gboolean
-io_gdip_bitmap_get_n_frames (GpBitmap *bitmap, guint *n_frames, gboolean timeDimension);
-gboolean
-io_gdip_bitmap_get_frame_delay (GpBitmap *bitmap, guint *delay);
-gboolean
-io_gdip_bitmap_select_frame (GpBitmap *bitmap, guint frame, gboolean timeDimension);
-gboolean
-io_gdip_bitmap_get_n_loops (GpBitmap *bitmap, guint *loops);
-
-gboolean
-io_gdip_bitmap_get_property_as_string (GpBitmap *bitmap, guint propertyId, gchar **str);
-
-gboolean
-io_gdip_save_bitmap_to_callback (GpBitmap *bitmap,
-                                 const CLSID *format,
-                                 const EncoderParameters *encoder_params,
-                                 GdkPixbufSaveFunc save_func,
-                                 gpointer user_data,
-                                 GError **error);
-
-GpBitmap *
-io_gdip_pixbuf_to_bitmap (GdkPixbuf *pixbuf);
-
 gboolean
 io_gdip_save_pixbuf (GdkPixbuf *pixbuf,
                      const WCHAR *format,

Modified: trunk/src/io-gdip.c
==============================================================================
--- trunk/src/io-gdip.c	(original)
+++ trunk/src/io-gdip.c	Sun Feb 24 22:42:26 2008
@@ -24,13 +24,13 @@
 #include "io-gdip-utils.h"
 
 void
-MODULE_ENTRY(gdi, fill_vtable) (GdkPixbufModule *module)
+MODULE_ENTRY (gdi, fill_vtable) (GdkPixbufModule *module)
 {
-  gdip_fill_vtable(module);
+  gdip_fill_vtable (module);
 }
 
 void
-MODULE_ENTRY(gdi, fill_info) (GdkPixbufFormat *info)
+MODULE_ENTRY (gdi, fill_info) (GdkPixbufFormat *info)
 {
   static GdkPixbufModulePattern signature[] = {
     { "  \x1   ", "zz znz", 100 }, /* ICO */
@@ -64,7 +64,7 @@
 
   info->name        = "gdi";
   info->signature   = signature;
-  info->description = "Win32 GDI+ image loader.";
+  info->description = _("The ICO, EMF, and WMF image formats");
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = GDK_PIXBUF_FORMAT_THREADSAFE;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]