[gegl] Add support for dataURI to gegl:load



commit 993e4ba16cbc5085ea21f6deb2aeb3d862ed39ee
Author: Jon Nordby <jononor gmail com>
Date:   Mon Jan 5 18:09:10 2015 +0100

    Add support for dataURI to gegl:load
    
    Peeks inside at the content-type to determine loader to use.
    Tested for png and jpg files.

 gegl/gegl-gio-private.h  |    6 ++++++
 gegl/gegl-gio.c          |   35 +++++++++++++++++++++++++++++++----
 operations/common/load.c |   27 +++++++++++++++++++++++++--
 3 files changed, 62 insertions(+), 6 deletions(-)
---
diff --git a/gegl/gegl-gio-private.h b/gegl/gegl-gio-private.h
index d918e4d..354f545 100644
--- a/gegl/gegl-gio-private.h
+++ b/gegl/gegl-gio-private.h
@@ -27,6 +27,12 @@ G_BEGIN_DECLS
 GInputStream *
 gegl_gio_open_input_stream(const gchar *uri, const gchar *path, GFile **out_file, GError **err);
 
+gboolean
+gegl_gio_uri_is_datauri(const gchar *uri);
+
+gchar *
+gegl_gio_datauri_get_content_type(const gchar *uri);
+
 #endif // __GEGL_GIO_PRIVATE_H__
 
 G_END_DECLS
diff --git a/gegl/gegl-gio.c b/gegl/gegl-gio.c
index b920eb4..39b3d72 100644
--- a/gegl/gegl-gio.c
+++ b/gegl/gegl-gio.c
@@ -27,9 +27,18 @@
 #include <gio/gunixinputstream.h>
 #endif
 
-// Note: header_item[0] is content-type, header_items[1] is encoding
+/**
+ * datauri_parse_header:
+ * @uri: URI to parse
+ * @raw_data_out: (out) (transfer full): return location for pointer to raw data, following header
+ * @header_items_no_out: (out) (transfer none): return location for number of items parsed from header
+ *
+ * Return value: (transfer full): header_item[0] is content-type, header_items[1] is encoding, free with 
g_strfreev()
+ *
+ * Note: currently private API
+ */
 static gchar **
-parse_datauri_header(const gchar *uri, gchar **raw_data_out, gint *header_items_no_out)
+datauri_parse_header(const gchar *uri, gchar **raw_data_out, gint *header_items_no_out)
 {
   // Determine data format
   const gchar * header_end = g_strstr_len (uri, -1, ",");
@@ -65,7 +74,7 @@ input_stream_datauri(const gchar *uri)
   GInputStream *stream = NULL;
   gchar * raw_data = NULL;
   gint header_items_no = 0;
-  gchar **header_items = parse_datauri_header(uri, &raw_data, &header_items_no);
+  gchar **header_items = datauri_parse_header(uri, &raw_data, &header_items_no);
   const gboolean is_base64 = header_items_no > 1 && g_strcmp0(header_items[1], "base64") == 0;
 
   if (is_base64) {
@@ -82,6 +91,24 @@ input_stream_datauri(const gchar *uri)
   return stream;
 }
 
+gchar *
+gegl_gio_datauri_get_content_type(const gchar *uri)
+{
+  gchar *content_type = NULL;
+  gint header_items_no = 0;
+  gchar **header_items = datauri_parse_header(uri, NULL, &header_items_no);
+  if (header_items_no)
+    content_type = g_strdup(header_items[0]);
+  g_strfreev(header_items);
+  return content_type;
+}
+
+gboolean
+gegl_gio_uri_is_datauri(const gchar *uri)
+{
+    return g_str_has_prefix(uri, "data:");
+}
+
 /**
  * gegl_gio_open_input_stream:
  * @uri: (allow none) URI to open. @uri is preferred over @path if both are set
@@ -112,7 +139,7 @@ gegl_gio_open_input_stream(const gchar *uri, const gchar *path, GFile **out_file
     }
   else if (uri && strlen(uri) > 0)
     {
-      if (g_str_has_prefix(uri, "data:"))
+      if (gegl_gio_uri_is_datauri(uri))
         {
           fis = input_stream_datauri(uri);
         }
diff --git a/operations/common/load.c b/operations/common/load.c
index 2794658..da39cdd 100644
--- a/operations/common/load.c
+++ b/operations/common/load.c
@@ -18,7 +18,7 @@
 
 #include "config.h"
 #include <glib/gi18n-lib.h>
-
+#include <gegl-gio-private.h>
 
 #ifdef GEGL_PROPERTIES
 
@@ -52,6 +52,17 @@ GEGL_DEFINE_DYNAMIC_OPERATION(GEGL_TYPE_OPERATION_META)
 
 #include <stdio.h>
 
+static gchar * const
+extension_from_mimetype(const gchar *mime)
+{
+    // XXX: maybe file loader opts should register mimetypes also?
+    static const gchar * const mime_prefix = "image/";
+    if (g_str_has_prefix(mime, mime_prefix)) {
+       return g_strdup_printf(".%s", mime+strlen(mime_prefix));
+    }
+    return NULL;
+}
+
 static void
 do_setup (GeglOperation *operation, const gchar *new_path, const gchar *new_uri)
 {
@@ -59,12 +70,24 @@ do_setup (GeglOperation *operation, const gchar *new_path, const gchar *new_uri)
 
   if (new_uri && strlen (new_uri) > 0)
       {
-        const gchar *extension = strrchr (new_uri, '.');
+        gchar *extension = NULL;
         const gchar *handler   = NULL;
+
+        if (gegl_gio_uri_is_datauri(new_uri))
+          {
+            gchar *mime = gegl_gio_datauri_get_content_type(new_uri);
+            extension = extension_from_mimetype(mime);
+            g_free(mime);
+          }
+        else
+            extension = g_strdup(strrchr (new_uri, '.'));
+
         if (extension)
             handler = gegl_extension_handler_get (extension);
         gegl_node_set (self->load, "operation", handler, NULL);
         gegl_node_set (self->load, "uri", new_uri, NULL);
+
+        g_free(extension);
       }
   else if (new_path && strlen (new_path) > 0)
     {


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