[gegl] webp: Port webp-save operation to GIO



commit ff766f23e3bb792c86b45be602c6d5a7976b53f4
Author: Martin Blanchard <tchaik gmx com>
Date:   Sun Mar 20 17:32:53 2016 +0100

    webp: Port webp-save operation to GIO
    
    Make use of gegl_gio_open_output_stream() service. No more direct
    fopen() call for output.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=763577

 operations/external/webp-save.c |  169 +++++++++++++++++++++++++++++----------
 1 files changed, 125 insertions(+), 44 deletions(-)
---
diff --git a/operations/external/webp-save.c b/operations/external/webp-save.c
index 1433025..a48462e 100644
--- a/operations/external/webp-save.c
+++ b/operations/external/webp-save.c
@@ -19,10 +19,11 @@
 #include "config.h"
 #include <glib/gi18n-lib.h>
 
+
 #ifdef GEGL_PROPERTIES
 
 property_file_path (path, _("File"), "")
-  description (_("Target file path."))
+  description (_("Target path and filename, use '-' for stdout"))
 
 property_int (quality, _("Quality"), 90)
   description (_("WebP compression quality"))
@@ -33,69 +34,149 @@ property_int (quality, _("Quality"), 90)
 #define GEGL_OP_SINK
 #define GEGL_OP_C_SOURCE webp-save.c
 
-#include "gegl-op.h"
+#include <gegl-op.h>
+#include <gegl-gio-private.h>
 #include <webp/encode.h>
-#include <stdio.h>
 
 static int
-write_func (const uint8_t* data, size_t data_size, const WebPPicture* const pic)
+write_to_stream (const uint8_t*     data,
+                 size_t             size,
+                 const WebPPicture* picture)
+{
+  GOutputStream *stream = (GOutputStream *) picture->custom_ptr;
+  GError *error = NULL;
+  gboolean success;
+  gsize written;
+
+  g_assert (stream);
+
+  success = g_output_stream_write_all (G_OUTPUT_STREAM (stream),
+                                       (const void *) data, size, &written,
+                                       NULL, &error);
+  if (!success || error != NULL)
+    {
+      g_warning ("%s", error->message);
+      g_error_free (error);
+      return 0;
+    }
+
+  return 1;
+}
+
+static gint
+save_RGBA (WebPPicture         *picture,
+           GeglBuffer          *input,
+           const GeglRectangle *result,
+           const Babl          *format)
 {
-  FILE* const out = (FILE*) pic->custom_ptr;
+  gint bytes_per_pixel, bytes_per_row;
+  uint8_t *buffer;
+
+  bytes_per_pixel = babl_format_get_bytes_per_pixel (format);
+  bytes_per_row = bytes_per_pixel * result->width;
+
+  buffer = g_try_new (uint8_t, bytes_per_row * result->height);
+
+  g_assert (buffer != NULL);
 
-  if (!data_size) return 1;
-  return fwrite (data, data_size, 1, out) == 1;
+  gegl_buffer_get (input, result, 1.0, format, buffer,
+                   GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+
+  WebPPictureImportRGBA (picture, buffer, bytes_per_row);
+
+  g_free (buffer);
+  return 0;
 }
 
 static gboolean
-process (GeglOperation       *operation,
-         GeglBuffer          *input,
-         const GeglRectangle *result,
-         gint                 level)
+export_webp (GeglOperation       *operation,
+             GeglBuffer          *input,
+             const GeglRectangle *result,
+             GOutputStream       *stream)
 {
   GeglProperties *o = GEGL_PROPERTIES (operation);
-  const GeglRectangle *bounds = gegl_buffer_get_extent (input);
-
-  FILE* file;
-  int status;
-
   WebPConfig config;
-  WebPPicture pic;
+  WebPPicture picture;
+  const Babl *format;
+  gint status;
 
-  if (!WebPConfigPreset (&config, WEBP_PRESET_DEFAULT, o->quality))
-    return FALSE;
+  g_return_val_if_fail (stream != NULL, FALSE);
 
-  if (!WebPValidateConfig (&config))
-    return FALSE;
+  if (!WebPConfigInit (&config) || !WebPPictureInit (&picture))
+    {
+      g_warning ("could not initialize WebP encoder");
+      return FALSE;
+    }
 
-  if (!WebPPictureInit (&pic))
-    return FALSE;
+  if (!WebPConfigPreset (&config, WEBP_PRESET_DEFAULT, o->quality))
+    {
+      g_warning("could not load WebP default preset");
+      return FALSE;
+    }
 
-  pic.width = bounds->width;
-  pic.height = bounds->height;
+  picture.width = result->width;
+  picture.height = result->height;
 
-  file = fopen (o->path, "wb");
-  pic.writer = write_func;
-  pic.custom_ptr = file;
+  format = babl_format ("R'G'B'A u8");
 
-  {
-    gint rowstride = bounds->width * sizeof (char) * 4;
-    gpointer temp = g_malloc (rowstride * bounds->height);
+  if (!WebPValidateConfig (&config))
+    {
+      g_warning ("WebP encoder configuration is invalid");
+      return FALSE;
+    }
 
-    gegl_buffer_get (input, bounds, 1.0, babl_format ("R'G'B'A u8"), temp,
-                     rowstride, GEGL_ABYSS_NONE);
+  picture.writer = write_to_stream;
+  picture.custom_ptr = stream;
 
-    WebPPictureImportRGBA (&pic, temp, rowstride);
+  if (save_RGBA (&picture, input, result, format))
+    {
+      g_warning ("could not pass pixels data to WebP encoder");
+      return FALSE;
+    }
 
-    g_free (temp);
-  }
+  status = WebPEncode (&config, &picture);
 
-  status = WebPEncode (&config, &pic);
-  WebPPictureFree (&pic);
-  fclose (file);
+  WebPPictureFree (&picture);
 
   return status ? TRUE : FALSE;
 }
 
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         const GeglRectangle *result,
+         gint                 level)
+{
+  GeglProperties *o = GEGL_PROPERTIES (operation);
+  GOutputStream *stream;
+  GFile *file = NULL;
+  GError *error = NULL;
+  gboolean status = TRUE;
+
+  stream = gegl_gio_open_output_stream (NULL, o->path, &file, &error);
+  if (stream == NULL)
+    {
+      status = FALSE;
+      g_warning ("%s", error->message);
+      goto cleanup;
+    }
+
+  if (!export_webp (operation, input, result, stream))
+    {
+      status = FALSE;
+      g_warning ("could not export WebP file");
+      goto cleanup;
+    }
+
+cleanup:
+  if (stream != NULL)
+    g_object_unref (stream);
+
+  if (file != NULL)
+    g_object_unref (file);
+
+  return status;
+}
 
 static void
 gegl_op_class_init (GeglOpClass *klass)
@@ -110,11 +191,11 @@ gegl_op_class_init (GeglOpClass *klass)
   sink_class->needs_full = TRUE;
 
   gegl_operation_class_set_keys (operation_class,
-  "name",        "gegl:webp-save",
-  "title",       _("WebP File Saver"),
-  "categories" , "output",
-  "description", _("WebP image saver."),
-   NULL);
+    "name",          "gegl:webp-save",
+    "title",       _("WebP File Saver"),
+    "categories",    "output",
+    "description", _("WebP image saver"),
+     NULL);
 
   gegl_extension_handler_register_saver (".webp", "gegl:webp-save");
 }


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