[gimp] plug-ins: port file-tiff to GIO



commit 4cf6dad0a0811d71f8f93d35e9a6fb4dc4effe48
Author: Michael Natterer <mitch gimp org>
Date:   Tue Apr 19 23:07:34 2016 +0100

    plug-ins: port file-tiff to GIO
    
    Using code from gegl:tiff-load and gegl:tiff-save which has a mode for
    local buffering if the input/output streams don't support seeking.
    Unfortunately this code is broken and is disabled for now.

 plug-ins/file-tiff/file-tiff-io.c |  367 ++++++++++++++++++++++++++++++++++---
 plug-ins/file-tiff/file-tiff.c    |    6 +-
 2 files changed, 346 insertions(+), 27 deletions(-)
---
diff --git a/plug-ins/file-tiff/file-tiff-io.c b/plug-ins/file-tiff/file-tiff-io.c
index c6e5520..03df383 100644
--- a/plug-ins/file-tiff/file-tiff-io.c
+++ b/plug-ins/file-tiff/file-tiff-io.c
@@ -32,12 +32,41 @@
 #include "file-tiff-io.h"
 
 
-static void   tiff_warning (const gchar *module,
-                            const gchar *fmt,
-                            va_list      ap) G_GNUC_PRINTF (2, 0);
-static void   tiff_error   (const gchar *module,
-                            const gchar *fmt,
-                            va_list      ap) G_GNUC_PRINTF (2, 0);
+typedef struct
+{
+  GFile         *file;
+  GObject       *stream;
+  GInputStream  *input;
+  GOutputStream *output;
+  gboolean       can_seek;
+
+  gchar         *buffer;
+  gsize          allocated;
+  gsize          used;
+  gsize          position;
+} TiffIO;
+
+
+static void      tiff_io_warning       (const gchar *module,
+                                        const gchar *fmt,
+                                        va_list      ap) G_GNUC_PRINTF (2, 0);
+static void      tiff_io_error         (const gchar *module,
+                                        const gchar *fmt,
+                                        va_list      ap) G_GNUC_PRINTF (2, 0);
+static tsize_t   tiff_io_read          (thandle_t    handle,
+                                        tdata_t      buffer,
+                                        tsize_t      size);
+static tsize_t   tiff_io_write         (thandle_t    handle,
+                                        tdata_t      buffer,
+                                        tsize_t      size);
+static toff_t    tiff_io_seek          (thandle_t    handle,
+                                        toff_t       offset,
+                                        gint         whence);
+static gint      tiff_io_close         (thandle_t    handle);
+static toff_t    tiff_io_get_file_size (thandle_t    handle);
+
+
+static TiffIO tiff_io = { 0, };
 
 
 TIFF *
@@ -45,33 +74,51 @@ tiff_open (GFile        *file,
            const gchar  *mode,
            GError      **error)
 {
-  gchar *filename = g_file_get_path (file);
+  TIFFSetWarningHandler (tiff_io_warning);
+  TIFFSetErrorHandler (tiff_io_error);
 
-  TIFFSetWarningHandler (tiff_warning);
-  TIFFSetErrorHandler (tiff_error);
+  tiff_io.file = file;
 
-#ifdef G_OS_WIN32
-  gunichar2 *utf16_filename = g_utf8_to_utf16 (filename, -1, NULL, NULL, error);
-
-  if (utf16_filename)
+  if (! strcmp (mode, "r"))
     {
-      TIFF *tif = TIFFOpenW (utf16_filename, mode);
+      tiff_io.input = G_INPUT_STREAM (g_file_read (file, NULL, error));
+      if (! tiff_io.input)
+        return NULL;
 
-      g_free (utf16_filename);
+      tiff_io.stream = G_OBJECT (tiff_io.input);
+    }
+  else
+    {
+      tiff_io.output = G_OUTPUT_STREAM (g_file_replace (file,
+                                                        NULL, FALSE,
+                                                        G_FILE_CREATE_NONE,
+                                                        NULL, error));
+      if (! tiff_io.output)
+        return FALSE;
 
-      return tif;
+      tiff_io.stream = G_OBJECT (tiff_io.output);
     }
 
-  return NULL;
-#else
-  return TIFFOpen (filename, mode);
+#if 0
+#warning FIXME !can_seek code is broken
+  tiff_io.can_seek = g_seekable_can_seek (G_SEEKABLE (tiff_io.stream));
 #endif
+  tiff_io.can_seek = TRUE;
+
+  return TIFFClientOpen ("file-tiff", mode,
+                         (thandle_t) &tiff_io,
+                         tiff_io_read,
+                         tiff_io_write,
+                         tiff_io_seek,
+                         tiff_io_close,
+                         tiff_io_get_file_size,
+                         NULL, NULL);
 }
 
 static void
-tiff_warning (const gchar *module,
-              const gchar *fmt,
-              va_list      ap)
+tiff_io_warning (const gchar *module,
+                 const gchar *fmt,
+                 va_list      ap)
 {
   gint tag = 0;
 
@@ -116,9 +163,9 @@ tiff_warning (const gchar *module,
 }
 
 static void
-tiff_error (const gchar *module,
-            const gchar *fmt,
-            va_list      ap)
+tiff_io_error (const gchar *module,
+               const gchar *fmt,
+               va_list      ap)
 {
   /* Workaround for: http://bugzilla.gnome.org/show_bug.cgi?id=132297
    * Ignore the errors related to random access and JPEG compression
@@ -128,3 +175,273 @@ tiff_error (const gchar *module,
 
   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
 }
+
+static tsize_t
+tiff_io_read (thandle_t handle,
+              tdata_t   buffer,
+              tsize_t   size)
+{
+  TiffIO *io    = (TiffIO *) handle;
+  GError *error = NULL;
+  gssize  read  = -1;
+
+  if (io->can_seek)
+    {
+      gsize bytes_read = 0;
+
+      if (! g_input_stream_read_all (io->input,
+                                     (void *) buffer, (gsize) size,
+                                     &bytes_read,
+                                     NULL, &error))
+        {
+          g_printerr ("%s", error->message);
+          g_clear_error (&error);
+        }
+
+      read = bytes_read;
+    }
+  else
+    {
+      if (io->position + size > io->used)
+        {
+          gsize missing;
+          gsize bytes_read;
+
+          missing = io->position + size - io->used;
+
+          if (io->used + missing > io->allocated)
+            {
+              gchar *new_buffer;
+              gsize  new_size = 1;
+              gsize  needed;
+
+              needed = io->used + missing - io->allocated;
+              while (new_size < io->allocated + needed)
+                new_size *= 2;
+
+              new_buffer = g_try_realloc (io->buffer, new_size);
+              if (! new_buffer)
+                return -1;
+
+              io->buffer    = new_buffer;
+              io->allocated = new_size;
+            }
+
+          if (! g_input_stream_read_all (io->input,
+                                         (void *) (io->buffer + io->used),
+                                         missing,
+                                         &bytes_read, NULL, &error))
+            {
+              g_printerr ("%s", error->message);
+              g_clear_error (&error);
+            }
+
+          io->used += bytes_read;
+        }
+
+      g_assert (io->position + size <= io->used);
+
+      memcpy (buffer, io->buffer + io->position, size);
+      io->position += size;
+
+      read = size;
+    }
+
+  return (tsize_t) read;
+}
+
+static tsize_t
+tiff_io_write (thandle_t handle,
+               tdata_t   buffer,
+               tsize_t   size)
+{
+  TiffIO *io      = (TiffIO *) handle;
+  GError *error   = NULL;
+  gssize  written = -1;
+
+  if (io->can_seek)
+    {
+      gsize bytes_written = 0;
+
+      if (! g_output_stream_write_all (io->output,
+                                       (void *) buffer, (gsize) size,
+                                       &bytes_written,
+                                       NULL, &error))
+        {
+          g_printerr ("%s", error->message);
+          g_clear_error (&error);
+        }
+
+      written = bytes_written;
+    }
+  else
+    {
+      if (io->position + size > io->allocated)
+        {
+          gchar *new_buffer;
+          gsize  new_size;
+
+          new_size = io->position + size;
+
+          new_buffer = g_try_realloc (io->buffer, new_size);
+          if (! new_buffer)
+            return -1;
+
+          io->buffer   = new_buffer;
+          io->allocated = new_size;
+        }
+
+      g_assert (io->position + size <= io->allocated);
+
+      memcpy (io->buffer + io->position, buffer, size);
+      io->position += size;
+
+      io->used = MAX (io->used, io->position);
+
+      written = size;
+    }
+
+  return (tsize_t) written;
+}
+
+static GSeekType
+lseek_to_seek_type (gint whence)
+{
+  switch (whence)
+    {
+    default:
+    case SEEK_SET:
+      return G_SEEK_SET;
+
+    case SEEK_CUR:
+      return G_SEEK_CUR;
+
+    case SEEK_END:
+      return G_SEEK_END;
+    }
+}
+
+static toff_t
+tiff_io_seek (thandle_t handle,
+              toff_t    offset,
+              gint      whence)
+{
+  TiffIO   *io       = (TiffIO *) handle;
+  GError   *error    = NULL;
+  gboolean  sought   = FALSE;
+  goffset   position = -1;
+
+  if (io->can_seek)
+    {
+      sought = g_seekable_seek (G_SEEKABLE (io->stream),
+                                (goffset) offset, lseek_to_seek_type (whence),
+                                NULL, &error);
+      if (sought)
+        {
+          position = g_seekable_tell (G_SEEKABLE (io->stream));
+        }
+      else
+        {
+          g_printerr ("%s", error->message);
+          g_clear_error (&error);
+        }
+    }
+  else
+    {
+      switch (whence)
+        {
+        default:
+        case SEEK_SET:
+          if (offset <= io->used)
+            position = io->position = offset;
+          break;
+
+        case SEEK_CUR:
+          if (io->position + offset <= io->used)
+            position = io->position += offset;
+          break;
+
+        case G_SEEK_END:
+          if (io->used + offset <= io->used)
+            position = io->position = io->used + offset;
+          break;
+        }
+    }
+
+  return (toff_t) position;
+}
+
+static gint
+tiff_io_close (thandle_t handle)
+{
+  TiffIO   *io     = (TiffIO *) handle;
+  GError   *error  = NULL;
+  gboolean  closed = FALSE;
+
+  if (io->input)
+    {
+      closed = g_input_stream_close (io->input, NULL, &error);
+    }
+  else
+    {
+      if (! io->can_seek && io->buffer && io->allocated)
+        {
+          if (! g_output_stream_write_all (io->output,
+                                           (void *) io->buffer,
+                                           io->allocated,
+                                           NULL, NULL, &error))
+            {
+              g_printerr ("%s", error->message);
+              g_clear_error (&error);
+            }
+        }
+
+      closed = g_output_stream_close (io->output, NULL, &error);
+    }
+
+  if (! closed)
+    {
+      g_printerr ("%s", error->message);
+      g_clear_error (&error);
+    }
+
+  g_object_unref (io->stream);
+  io->stream = NULL;
+  io->input  = NULL;
+  io->output = NULL;
+
+  g_free (io->buffer);
+  io->buffer = NULL;
+
+  io->allocated = 0;
+  io->used      = 0;
+  io->position  = 0;
+
+  return closed ? 0 : -1;
+}
+
+static toff_t
+tiff_io_get_file_size (thandle_t handle)
+{
+  TiffIO    *io    = (TiffIO *) handle;
+  GError    *error = NULL;
+  GFileInfo *info;
+  goffset    size = 0;
+
+  info = g_file_query_info (io->file,
+                            G_FILE_ATTRIBUTE_STANDARD_SIZE,
+                            G_FILE_QUERY_INFO_NONE,
+                            NULL, &error);
+  if (! info)
+    {
+      g_printerr ("%s", error->message);
+      g_clear_error (&error);
+    }
+  else
+    {
+      size = g_file_info_get_size (info);
+      g_object_unref (info);
+    }
+
+  return (toff_t) size;
+}
diff --git a/plug-ins/file-tiff/file-tiff.c b/plug-ins/file-tiff/file-tiff.c
index cd88955..5135d13 100644
--- a/plug-ins/file-tiff/file-tiff.c
+++ b/plug-ins/file-tiff/file-tiff.c
@@ -145,6 +145,7 @@ query (void)
                           load_args, load_return_vals);
 
   gimp_register_file_handler_mime (LOAD_PROC, "image/tiff");
+  gimp_register_file_handler_uri (LOAD_PROC);
   gimp_register_magic_load_handler (LOAD_PROC,
                                     "tif,tiff",
                                     "",
@@ -165,6 +166,7 @@ query (void)
                           save_args_old, NULL);
 
   gimp_register_file_handler_mime (SAVE_PROC, "image/tiff");
+  gimp_register_file_handler_uri (SAVE_PROC);
   gimp_register_save_handler (SAVE_PROC, "tif,tiff", "");
 
   gimp_install_procedure (SAVE2_PROC,
@@ -207,7 +209,7 @@ run (const gchar      *name,
 
   if (strcmp (name, LOAD_PROC) == 0)
     {
-      GFile *file = g_file_new_for_path (param[1].data.d_string);
+      GFile *file = g_file_new_for_uri (param[1].data.d_string);
       TIFF  *tif;
 
       tif = tiff_open (file, "r", &error);
@@ -456,7 +458,7 @@ run (const gchar      *name,
           GFile *file;
           gint   saved_bpp;
 
-          file = g_file_new_for_path (param[3].data.d_string);
+          file = g_file_new_for_uri (param[3].data.d_string);
 
           if (save_image (file, &tsvals,
                           image, drawable, orig_image, image_comment,


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