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



Author: doml
Date: Thu Feb 21 23:45:44 2008
New Revision: 27
URL: http://svn.gnome.org/viewvc/gdip-pixbuf-loader?rev=27&view=rev

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

	* src/*.[ch]: If you #define GDIP_TEST_SAVING, you should be able to save
	a pixbuf to a PNG via GDI+. WARNING: UNTESTED CODE

Modified:
   trunk/ChangeLog
   trunk/src/io-gdip-native.h
   trunk/src/io-gdip-utils.c
   trunk/src/io-gdip-utils.h
   trunk/src/io-gdip.c

Modified: trunk/src/io-gdip-native.h
==============================================================================
--- trunk/src/io-gdip-native.h	(original)
+++ trunk/src/io-gdip-native.h	Thu Feb 21 23:45:44 2008
@@ -158,6 +158,24 @@
 };
 typedef struct _EncoderParameters EncoderParameters;
 
+struct _ImageCodecInfo
+{
+    CLSID Clsid;
+    GUID  FormatID;
+    const WCHAR* CodecName;
+    const WCHAR* DllName;
+    const WCHAR* FormatDescription;
+    const WCHAR* FilenameExtension;
+    const WCHAR* MimeType;
+    DWORD Flags;
+    DWORD Version;
+    DWORD SigCount;
+    DWORD SigSize;
+    const BYTE* SigPattern;
+    const BYTE* SigMask;
+};
+typedef struct _ImageCodecInfo ImageCodecInfo;
+
 #ifndef IStream_Release
 #define IStream_Release(This) (This)->lpVtbl->Release(This)
 #endif
@@ -188,4 +206,7 @@
 typedef GpStatus (WINGDIPAPI* GdipSaveImageToStreamFunc) (GpImage *image, IStream* stream, const CLSID* clsidEncoder, 
                                                           const EncoderParameters* encoderParams);
 
+typedef GpStatus (WINGDIAPI *GetImageEncodersFunc) (UINT numEncoders, UINT size, ImageCodecInfo *encoders);
+typedef GpStatus (WINGDIAPI *GetImageEncodersSizeFunc) (UINT *numEncoders, UINT *size);
+
 #endif

Modified: trunk/src/io-gdip-utils.c
==============================================================================
--- trunk/src/io-gdip-utils.c	(original)
+++ trunk/src/io-gdip-utils.c	Thu Feb 21 23:45:44 2008
@@ -21,11 +21,13 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
 #define INITGUID
 #include "io-gdip-native.h"
+#include "io-gdip-utils.h"
 #include "io-gdip-propertytags.h"
 #include <ole2.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
 
 static GdiplusStartupFunc GdiplusStartup;
 static GdipCreateBitmapFromStreamFunc GdipCreateBitmapFromStream;
@@ -43,6 +45,10 @@
 static GdipCreateBitmapFromScan0Func GdipCreateBitmapFromScan0;
 static GdipSaveImageToStreamFunc GdipSaveImageToStream;
 
+/* apparently these don't exist until GDI+ 1.1 or later */
+static GetImageEncodersFunc GetImageEncoders;
+static GetImageEncodersSizeFunc GetImageEncodersSize;
+
 extern void gdip_propegate_error (GError ** err, const char * reason, gint code);
 
 DEFINE_GUID(FrameDimensionTime, 0x6aedbd6d,0x3fb5,0x418a,0x83,0xa6,0x7f,0x45,0x22,0x9d,0xc8,0x72);
@@ -66,9 +72,18 @@
     return FALSE;
 
 #define LOOKUP(func) \
-  func = (func##Func) GetProcAddress(gdipluslib, #func); \
-  if (!func) \
-    return FALSE
+  do { \
+    func = (func##Func) GetProcAddress(gdipluslib, #func); \
+    if (!func) {\
+      g_warning("Couldn't load function: %s\n", #func); \
+      return FALSE; \
+    } \
+  } while (0)
+
+#define TRY_LOOKUP(func) \
+  do { \
+    func = (func##Func) GetProcAddress(gdipluslib, #func); \
+  } while (0)
 
   LOOKUP (GdiplusStartup);
   LOOKUP (GdipCreateBitmapFromStream);
@@ -85,12 +100,70 @@
   LOOKUP (GdipGetPropertyIdList);
   LOOKUP (GdipCreateBitmapFromScan0);
   LOOKUP (GdipSaveImageToStream);
+  TRY_LOOKUP (GetImageEncoders);
+  TRY_LOOKUP (GetImageEncodersSize);
 
 #undef LOOKUP
   
   return (GdiplusStartup (&gdiplusToken, &input, NULL) == 0 ? TRUE : FALSE);
 }
 
+static int 
+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);
+      return -1;
+    }
+  else
+    {
+      static CLSID gdip_png_guid = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x0, 0x0, 0xf8, 0x1e, 0xf3, 0x2e } };
+
+      if (wcscmp(format, L"image/png") == 0)
+        {
+          *pClsid = gdip_png_guid;
+          return 0;
+        }
+
+      /*
+        todo:
+        image/bmp
+        image/jpeg
+        image/gif
+        image/tiff
+      */
+
+      return -1;
+    }
+}
+
 static HGLOBAL
 io_gdip_buffer_to_hglobal (const gchar * buffer, size_t size)
 {
@@ -213,6 +286,39 @@
   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)
 {

Modified: trunk/src/io-gdip-utils.h
==============================================================================
--- trunk/src/io-gdip-utils.h	(original)
+++ trunk/src/io-gdip-utils.h	Thu Feb 21 23:45:44 2008
@@ -67,4 +67,12 @@
 GpBitmap *
 io_gdip_pixbuf_to_bitmap (GdkPixbuf *pixbuf);
 
+gboolean
+io_gdip_save_pixbuf (GdkPixbuf *pixbuf,
+                     const WCHAR *format,
+                     const EncoderParameters *encoder_params,
+                     GdkPixbufSaveFunc save_func,
+                     gpointer user_data,
+                     GError **error);
+
 #endif

Modified: trunk/src/io-gdip.c
==============================================================================
--- trunk/src/io-gdip.c	(original)
+++ trunk/src/io-gdip.c	Thu Feb 21 23:45:44 2008
@@ -276,6 +276,37 @@
   return TRUE;
 }
 
+/*
+  The MIME types of the encoders built into Microsoft Windows GDI+ are as follows: 
+
+    * image/bmp
+    * image/jpeg
+    * image/gif
+    * image/tiff
+    * image/png 
+*/
+
+#ifdef GDIP_TEST_SAVING
+static gboolean
+gdk_pixbuf__gdip_image_save_PNG_to_callback (GdkPixbufSaveFunc   save_func,
+                                             gpointer            user_data,
+                                             GdkPixbuf          *pixbuf,
+                                             gchar             **keys,
+                                             gchar             **values,
+                                             GError            **error)
+{
+  /* TODO: support exif data and the like */
+  EncoderParameters *encoder_params = NULL;
+  gboolean status;
+
+  status = io_gdip_save_pixbuf (pixbuf, L"image/png", encoder_params, save_func, user_data, error);
+
+  g_free (encoder_params);
+
+  return status;
+}
+#endif
+
 void
 fill_vtable (GdkPixbufModule *module)
 {
@@ -284,6 +315,10 @@
   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;
+
+#ifdef GDIP_TEST_SAVING
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_PNG_to_callback;
+#endif
 }
 
 void
@@ -346,4 +381,8 @@
   info->mime_types  = mime_types;
   info->extensions  = extensions;
   info->flags       = 0;
+
+#ifdef GDIP_TEST_SAVING
+  info->flags |= GDK_PIXBUF_FORMAT_WRITABLE;
+#endif
 }



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