[gtk/image-loading: 11/36] Redo tiff load/save without streams




commit 3d41f25d434453eaf5b58ea3db89c69ad7deabdd
Author: Benjamin Otte <otte redhat com>
Date:   Tue Sep 14 02:03:55 2021 +0200

    Redo tiff load/save without streams
    
    Less code.

 gdk/loaders/gdktiff.c | 268 +++++++++++++++++---------------------------------
 1 file changed, 88 insertions(+), 180 deletions(-)
---
diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c
index 74be02cbe5..3be4594acb 100644
--- a/gdk/loaders/gdktiff.c
+++ b/gdk/loaders/gdktiff.c
@@ -38,19 +38,16 @@
 
 typedef struct
 {
-  GObject *stream;
-  GInputStream *input;
-  GOutputStream *output;
-
-  gchar *buffer;
-  gsize allocated;
-  gsize used;
+  GBytes **out_bytes;
+  gchar *data;
+  gsize size;
   gsize position;
 } TiffIO;
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
-
+static void
+tiff_io_warning (const char *module,
+                 const char *fmt,
+                 va_list     ap) G_GNUC_PRINTF(2, 0);
 static void
 tiff_io_warning (const char *module,
                  const char *fmt,
@@ -59,6 +56,10 @@ tiff_io_warning (const char *module,
   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
 }
 
+static void
+tiff_io_error (const char *module,
+               const char *fmt,
+               va_list     ap) G_GNUC_PRINTF(2, 0);
 static void
 tiff_io_error (const char *module,
                const char *fmt,
@@ -67,222 +68,144 @@ tiff_io_error (const char *module,
   g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, ap);
 }
 
-#pragma GCC diagnostic pop
-
 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;
-  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);
-    }
+  gsize read;
 
-  read = bytes_read;
+  read = MIN (size, io->size - io->position);
+
+  memcpy (buffer, io->data + io->position, read);
+  io->position += read;
 
   return (tsize_t) read;
 }
 
+static tsize_t
+tiff_io_no_write (thandle_t handle,
+                  tdata_t   buffer,
+                  tsize_t   size)
+{
+  errno = EINVAL;
+  return (tsize_t) -1;
+}
+
 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;
-  gsize bytes_written = 0;
-
-  if (! g_output_stream_write_all (io->output,
-                                   (void *) buffer, (gsize) size,
-                                   &bytes_written,
-                                   NULL, &error))
+
+  if (io->size - io->position < size)
     {
-      g_printerr ("%s", error->message);
-      g_clear_error (&error);
+      io->size = io->position + size;
+      io->data = g_realloc (io->data, io->size);
     }
 
-  written = bytes_written;
+  memcpy (io->data + io->position, buffer, size);
+  io->position += size;
 
-  return (tsize_t) written;
+  return (tsize_t) size;
 }
 
-static GSeekType
-lseek_to_seek_type (int whence)
+static toff_t
+tiff_io_seek (thandle_t handle,
+              toff_t    offset,
+              int       whence)
 {
+  TiffIO *io = (TiffIO *) handle;
+
   switch (whence)
     {
     default:
+      errno = EINVAL;
+      return -1;
     case SEEK_SET:
-      return G_SEEK_SET;
+      break;
     case SEEK_CUR:
-      return G_SEEK_CUR;
+      offset += io->position;
+      break;
     case SEEK_END:
-      return G_SEEK_END;
+      offset += io->size;
+      break;
     }
-}
-
-static toff_t
-tiff_io_seek (thandle_t handle,
-              toff_t    offset,
-              int       whence)
-{
-  TiffIO *io = (TiffIO *) handle;
-  GError *error = NULL;
-  gboolean sought = FALSE;
-  goffset position = -1;
-
-  sought = g_seekable_seek (G_SEEKABLE (io->stream),
-                            (goffset) offset, lseek_to_seek_type (whence),
-                            NULL, &error);
-  if (sought)
+  if (offset < 0)
     {
-      position = g_seekable_tell (G_SEEKABLE (io->stream));
+      errno = EINVAL;
+      return -1;
     }
-  else
+  if (offset > io->size)
     {
-      g_printerr ("%s", error->message);
-      g_clear_error (&error);
+      /* Linux apparently can do that */
+      errno = EINVAL;
+      return -1;
     }
 
-  return (toff_t) position;
+  io->position = offset;
+
+  return offset;
 }
 
 static int
 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->output)
-    closed = g_output_stream_close (io->output, NULL, &error);
 
-  if (!closed)
-    {
-      g_printerr ("%s", error->message);
-      g_clear_error (&error);
-    }
-
-  g_clear_object (&io->stream);
-  io->input = NULL;
-  io->output = NULL;
-
-  g_clear_pointer (&io->buffer, g_free);
-
-  io->allocated = 0;
-  io->used = 0;
-  io->position  = 0;
+  if (io->out_bytes)
+    *io->out_bytes = g_bytes_new_take (io->data, io->size);
 
   g_free (io);
 
-  return closed ? 0 : -1;
+  return 0;
 }
 
-static goffset
-input_stream_query_size (GInputStream *stream)
+static toff_t
+tiff_io_get_file_size (thandle_t handle)
 {
-  goffset size = 0;
-
-  while (G_IS_FILTER_INPUT_STREAM (stream))
-    stream = g_filter_input_stream_get_base_stream (G_FILTER_INPUT_STREAM (stream));
-
-  if (G_IS_FILE_INPUT_STREAM (stream))
-    {
-      GFileInfo *info;
-
-      info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (stream),
-                                             G_FILE_ATTRIBUTE_STANDARD_SIZE,
-                                             NULL,
-                                             NULL);
-      if (info)
-        {
-          size = g_file_info_get_size (info);
-          g_object_unref (info);
-        }
-    }
+  TiffIO *io = (TiffIO *) handle;
 
-  return size;
+  return io->size;
 }
 
-static goffset
-output_stream_query_size (GOutputStream *stream)
+static TIFF *
+tiff_open_read (GBytes *bytes)
 {
-  goffset size = 0;
-
-  while (G_IS_FILTER_OUTPUT_STREAM (stream))
-    stream = g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (stream));
-
-  if (G_IS_FILE_OUTPUT_STREAM (stream))
-    {
-      GFileInfo *info;
-
-      info = g_file_output_stream_query_info (G_FILE_OUTPUT_STREAM (stream),
-                                              G_FILE_ATTRIBUTE_STANDARD_SIZE,
-                                              NULL,
-                                              NULL);
-      if (info)
-        {
-          size = g_file_info_get_size (info);
-          g_object_unref (info);
-        }
-    }
+  TiffIO *io;
 
-  return size;
-}
+  TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
+  TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
 
-static toff_t
-tiff_io_get_file_size (thandle_t handle)
-{
-  TiffIO *io = (TiffIO *) handle;
+  io = g_new0 (TiffIO, 1);
 
-  if (io->input)
-    return (toff_t) input_stream_query_size (io->input);
-  else if (io->output)
-    return (toff_t) output_stream_query_size (io->output);
+  io->data = (char *) g_bytes_get_data (bytes, &io->size);
 
-  return (toff_t) 0;
+  return TIFFClientOpen ("GTK-read", "r",
+                         (thandle_t) io,
+                         tiff_io_read,
+                         tiff_io_no_write,
+                         tiff_io_seek,
+                         tiff_io_close,
+                         tiff_io_get_file_size,
+                         NULL, NULL);
 }
 
 static TIFF *
-tiff_open (gpointer      stream,
-           const gchar  *mode,
-           GError      **error)
+tiff_open_write (GBytes **result)
 {
+  TiffIO *io;
+
   TIFFSetWarningHandler ((TIFFErrorHandler) tiff_io_warning);
   TIFFSetErrorHandler ((TIFFErrorHandler) tiff_io_error);
-  TiffIO *io;
 
   io = g_new0 (TiffIO, 1);
 
-  if (strcmp (mode, "r") == 0)
-    {
-      io->input = G_INPUT_STREAM (stream);
-      io->stream = g_object_ref (G_OBJECT (stream));
-    }
-  else if (strcmp (mode, "w") == 0)
-    {
-      io->output = G_OUTPUT_STREAM (stream);
-      io->stream = g_object_ref (G_OBJECT (stream));
-    }
-  else
-    {
-      g_assert_not_reached ();
-    }
+  io->out_bytes = result;
 
-  return TIFFClientOpen ("GTK", mode,
+  return TIFFClientOpen ("GTK-write", "w",
                          (thandle_t) io,
                          tiff_io_read,
                          tiff_io_write,
@@ -338,7 +261,6 @@ static struct {
 GBytes *
 gdk_save_tiff (GdkTexture *texture)
 {
-  GOutputStream *stream;
   TIFF *tif;
   int width, height, stride;
   guint16 bits_per_sample = 0;
@@ -347,17 +269,11 @@ gdk_save_tiff (GdkTexture *texture)
   const guchar *line;
   const guchar *data;
   guchar *new_data = NULL;
-  GBytes *bytes;
+  GBytes *result = NULL;
   GdkTexture *memory_texture;
   GdkMemoryFormat format;
 
-  stream = g_memory_output_stream_new (NULL, 0, g_realloc, g_free);
-  tif = tiff_open (stream, "w", NULL);
-  if (!tif)
-    {
-      g_object_unref (stream);
-      return NULL;
-    }
+  tif = tiff_open_write (&result);
 
   width = gdk_texture_get_width (texture);
   height = gdk_texture_get_height (texture);
@@ -422,7 +338,6 @@ gdk_save_tiff (GdkTexture *texture)
           TIFFClose (tif);
           g_free (new_data);
           g_object_unref (memory_texture);
-          g_object_unref (stream);
           return NULL;
         }
 
@@ -432,13 +347,12 @@ gdk_save_tiff (GdkTexture *texture)
   TIFFFlushData (tif);
   TIFFClose (tif);
 
+  g_assert (result);
+
   g_free (new_data);
   g_object_unref (memory_texture);
 
-  bytes = g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (stream));
-  g_object_unref (stream);
-
-  return bytes;
+  return result;
 }
 
 static GdkTexture *
@@ -480,7 +394,6 @@ GdkTexture *
 gdk_load_tiff (GBytes  *input_bytes,
                GError **error)
 {
-  GInputStream *stream;
   TIFF *tif;
   guint16 samples_per_pixel;
   guint16 bits_per_sample;
@@ -496,12 +409,7 @@ gdk_load_tiff (GBytes  *input_bytes,
   GBytes *bytes;
   GdkTexture *texture;
 
-  stream = g_memory_input_stream_new_from_bytes (input_bytes);
-  tif = tiff_open (stream, "r", error);
-  g_object_unref (stream);
-
-  if (!tif)
-    return NULL;
+  tif = tiff_open_read (input_bytes);
 
   TIFFSetDirectory (tif, 0);
 


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