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



Author: doml
Date: Fri Feb 22 17:36:29 2008
New Revision: 29
URL: http://svn.gnome.org/viewvc/gdip-pixbuf-loader?rev=29&view=rev

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

	* src/*.[ch]: Saving images to PNG now works. Conditionally compiled
	until I get GdkPixbuf's saving architecture straightened out.

Modified:
   trunk/ChangeLog
   trunk/src/io-gdip-native.h
   trunk/src/io-gdip-utils.c
   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	Fri Feb 22 17:36:29 2008
@@ -206,7 +206,8 @@
 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);
+typedef GpStatus (WINGDIAPI* GetImageEncodersFunc) (UINT numEncoders, UINT size, ImageCodecInfo *encoders);
+typedef GpStatus (WINGDIAPI* GetImageEncodersSizeFunc) (UINT *numEncoders, UINT *size);
+typedef GpStatus (WINGDIPAPI* GdipBitmapSetPixelFunc) (GpBitmap* bitmap, INT x, INT y, ARGB color);
 
 #endif

Modified: trunk/src/io-gdip-utils.c
==============================================================================
--- trunk/src/io-gdip-utils.c	(original)
+++ trunk/src/io-gdip-utils.c	Fri Feb 22 17:36:29 2008
@@ -44,6 +44,7 @@
 static GdipGetPropertyIdListFunc GdipGetPropertyIdList;
 static GdipCreateBitmapFromScan0Func GdipCreateBitmapFromScan0;
 static GdipSaveImageToStreamFunc GdipSaveImageToStream;
+static GdipBitmapSetPixelFunc GdipBitmapSetPixel;
 
 /* apparently these don't exist until GDI+ 1.1 or later */
 static GetImageEncodersFunc GetImageEncoders;
@@ -98,9 +99,11 @@
   LOOKUP (GdipGetPropertyIdList);
   LOOKUP (GdipCreateBitmapFromScan0);
   LOOKUP (GdipSaveImageToStream);
+  LOOKUP (GdipBitmapSetPixel);
   TRY_LOOKUP (GetImageEncoders);
   TRY_LOOKUP (GetImageEncodersSize);
 
+#undef TRY_LOOKUP
 #undef LOOKUP
 
   input.GdiplusVersion = 1;
@@ -192,6 +195,7 @@
   HRESULT hr;  
   IStream *streamOut = NULL;
   gboolean success = FALSE;
+  guint64 zero = 0;
 
   hr = CreateStreamOnHGlobal (NULL, TRUE, &streamOut);
   if (!SUCCEEDED(hr))
@@ -207,7 +211,14 @@
       return FALSE;
     }
 
-  while (1)
+  /* 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;
@@ -243,41 +254,44 @@
   n_channels = gdk_pixbuf_get_n_channels(pixbuf);
   pixels = gdk_pixbuf_get_pixels(pixbuf);
 
-  if (n_channels == 3)
-    {
-      /* rgb24 */
-      GdipCreateBitmapFromScan0(width, height, stride, PixelFormat24bppRGB, pixels, &bitmap);
-    }
-  else if (n_channels == 4)
+  if (n_channels == 3 || n_channels == 4)
     {
-      /* rgba. need to convert to argb */
-      guint8 *pixels_dup;
-
-      pixels_dup = g_memdup(pixels, height * stride);
-      if (pixels_dup)
+      /* rgbX. need to convert to argb */
+      GdipCreateBitmapFromScan0(width, height, stride, PixelFormat32bppARGB, NULL, &bitmap);
+      
+      if (bitmap)
         {
-          int y;
+          int x, y;
+
           for (y = 0; y < height; y++)
             {
-              int x;
-
               for (x = 0; x < width; x++)
                 {
-                  guint32 pixel;
-                  guchar *b = pixels_dup + (y * stride + (x * n_channels));
+                  ARGB p;
+                  guchar *base = pixels + (y * stride + (x * n_channels));
+                  guint8 alpha = 0xff;
+                  
+                  if (n_channels == 4)
+                    {
+                      alpha = base[3];
+                    }
                   
-                  memcpy (&pixel, b, sizeof (guint32));
+                  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);
+                    }
                   
-                  /* swap rgba -> argb */
-                  b[0] = (pixel & 0xff000000) >> 24;
-                  b[1] = (pixel & 0x00ff0000) >> 16;
-                  b[2] = (pixel & 0x0000ff00) >> 8;
-                  b[3] = (pixel & 0x000000ff) >> 0;                  
+                  GdipBitmapSetPixel(bitmap, x, y, p);
                 }
             }
-          
-          GdipCreateBitmapFromScan0(width, height, stride, PixelFormat32bppARGB, pixels_dup, &bitmap);
-          g_free(pixels_dup);
         }
     }
   else
@@ -300,7 +314,7 @@
   CLSID clsid;
   gboolean success;
 
-  if (-1 != GetEncoderClsid(format, &clsid))
+  if (-1 == GetEncoderClsid(format, &clsid))
     {
       gdip_propegate_error (error, "Unsupported format", GDK_PIXBUF_ERROR_FAILED);
       return FALSE;

Modified: trunk/src/io-gdip.c
==============================================================================
--- trunk/src/io-gdip.c	(original)
+++ trunk/src/io-gdip.c	Fri Feb 22 17:36:29 2008
@@ -276,6 +276,28 @@
   return TRUE;
 }
 
+gboolean
+gdip_save_to_file_callback (const gchar *buf,
+                            gsize        count,
+                            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;
+}
+
 /*
   The MIME types of the encoders built into Microsoft Windows GDI+ are as follows: 
 
@@ -305,6 +327,16 @@
 
   return status;
 }
+
+static gboolean
+gdk_pixbuf__gdip_image_save_PNG (FILE          *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_PNG_to_callback(gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
 #endif
 
 /* meant to be shared across various GDI+ plugins, since we'll need multiple plugins to support saving to multiple formats */
@@ -325,6 +357,7 @@
 
 #ifdef GDIP_TEST_SAVING
   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 */
 #endif
 }
 
@@ -382,14 +415,20 @@
     NULL
   };
 
+#ifdef GDIP_TEST_SAVING
+  info->name        = "png";
+#else
   info->name        = "Win32 GDI+";
+#endif
+
   info->signature   = signature;
   info->description = "Win32 GDI+ JPEG, Tiff and PNG loader.";
   info->mime_types  = mime_types;
   info->extensions  = extensions;
-  info->flags       = 0;
 
 #ifdef GDIP_TEST_SAVING
-  info->flags |= GDK_PIXBUF_FORMAT_WRITABLE;
+  info->flags = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+#else
+  info->flags       = 0;
 #endif
 }



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