[gtk/wip/otte/colorspace: 3/19] tiff: Refactor




commit c2302f80037725c9397c3b9a7b6535f217fe6e4f
Author: Benjamin Otte <otte redhat com>
Date:   Sun Oct 17 14:27:03 2021 +0200

    tiff: Refactor
    
    Now we support all the formats.

 gdk/loaders/gdktiff.c | 151 +++++++++++++++++++-------------------------------
 1 file changed, 57 insertions(+), 94 deletions(-)
---
diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c
index 994f50e353..ec68b7b8fa 100644
--- a/gdk/loaders/gdktiff.c
+++ b/gdk/loaders/gdktiff.c
@@ -220,129 +220,89 @@ tiff_open_write (GBytes **result)
                          NULL, NULL);
 }
 
-/* }}} */
-/* {{{ Format conversion */
-
-static void
-flip_02 (guchar *data,
-         int     width,
-         int     height,
-         int     stride)
-{ 
-  gsize x, y;
-  
-  for (y = 0; y < height; y++)
-    {
-      for (x = 0; x < width; x++)
-        {
-          guchar tmp;
-          tmp = data[x * 4];
-          data[x * 4] = data[x * 4 + 2];
-          data[x * 4 + 2] = tmp;
-        }
-      data += stride;
-    }
-}
-
 /* }}} */
 /* {{{ Public API */
 
-static struct {
+typedef struct _FormatData FormatData;
+struct _FormatData {
   GdkMemoryFormat format;
   guint16 bits_per_sample;
   guint16 samples_per_pixel;
   guint16 sample_format;
-} format_data[] = {
-  { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,            8, 4, SAMPLEFORMAT_UINT   },
-  { GDK_MEMORY_R8G8B8,                            8, 3, SAMPLEFORMAT_UINT   },
-  { GDK_MEMORY_R16G16B16,                        16, 3, SAMPLEFORMAT_UINT   },
-  { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,       16, 4, SAMPLEFORMAT_UINT   },
-  { GDK_MEMORY_R16G16B16_FLOAT,                  16, 3, SAMPLEFORMAT_IEEEFP },
-  { GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, 16, 4, SAMPLEFORMAT_IEEEFP },
-  { GDK_MEMORY_R32G32B32_FLOAT,                  32, 3, SAMPLEFORMAT_IEEEFP },
-  { GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, 32, 4, SAMPLEFORMAT_IEEEFP },
+  guint16 alpha_samples;
+};
+
+static const FormatData format_data[] = {
+  [GDK_MEMORY_B8G8R8A8_PREMULTIPLIED]           = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,            8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_A8R8G8B8_PREMULTIPLIED]           = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,            8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_R8G8B8A8_PREMULTIPLIED]           = { GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,            8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_B8G8R8A8]                         = { GDK_MEMORY_R8G8B8A8,                          8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_A8R8G8B8]                         = { GDK_MEMORY_R8G8B8A8,                          8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_R8G8B8A8]                         = { GDK_MEMORY_R8G8B8A8,                          8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_A8B8G8R8]                         = { GDK_MEMORY_R8G8B8A8,                          8, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_R8G8B8]                           = { GDK_MEMORY_R8G8B8,                            8, 3, 
SAMPLEFORMAT_UINT,   0                      }, 
+  [GDK_MEMORY_B8G8R8]                           = { GDK_MEMORY_R8G8B8,                            8, 3, 
SAMPLEFORMAT_UINT,   0                      },
+  [GDK_MEMORY_R16G16B16]                        = { GDK_MEMORY_R16G16B16,                        16, 3, 
SAMPLEFORMAT_UINT,   0                      },
+  [GDK_MEMORY_R16G16B16A16_PREMULTIPLIED]       = { GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,       16, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_R16G16B16A16]                     = { GDK_MEMORY_R16G16B16A16,                     16, 4, 
SAMPLEFORMAT_UINT,   EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_R16G16B16_FLOAT]                  = { GDK_MEMORY_R16G16B16_FLOAT,                  16, 3, 
SAMPLEFORMAT_IEEEFP, 0                      },
+  [GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = { GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED, 16, 4, 
SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_R16G16B16A16_FLOAT]               = { GDK_MEMORY_R16G16B16A16_FLOAT,               16, 4, 
SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_UNASSALPHA },
+  [GDK_MEMORY_R32G32B32_FLOAT]                  = { GDK_MEMORY_R32G32B32_FLOAT,                  32, 3, 
SAMPLEFORMAT_IEEEFP, 0                      },
+  [GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = { GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED, 32, 4, 
SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_ASSOCALPHA },
+  [GDK_MEMORY_R32G32B32A32_FLOAT]               = { GDK_MEMORY_R32G32B32A32_FLOAT,               32, 4, 
SAMPLEFORMAT_IEEEFP, EXTRASAMPLE_UNASSALPHA },
 };
 
+/* if this fails, somebody forgot to add formats above */
+G_STATIC_ASSERT (G_N_ELEMENTS (format_data) == GDK_MEMORY_N_FORMATS);
+
 GBytes *
 gdk_save_tiff (GdkTexture *texture)
 {
   TIFF *tif;
   int width, height, stride;
-  guint16 bits_per_sample = 0;
-  guint16 samples_per_pixel = 0;
-  guint16 sample_format = 0;
   const guchar *line;
   const guchar *data;
-  guchar *new_data = NULL;
   GBytes *result = NULL;
-  GdkTexture *memory_texture;
+  GdkMemoryTexture *memtex;
   GdkMemoryFormat format;
+  const FormatData *fdata = NULL;
 
   tif = tiff_open_write (&result);
 
   width = gdk_texture_get_width (texture);
   height = gdk_texture_get_height (texture);
-
   format = gdk_texture_get_format (texture);
-  memory_texture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format));
+  fdata = &format_data[format];
 
-  for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
-    {
-      if (format == format_data[i].format)
-        {
-          data = gdk_memory_texture_get_data (GDK_MEMORY_TEXTURE (memory_texture));
-          stride = gdk_memory_texture_get_stride (GDK_MEMORY_TEXTURE (memory_texture));
-          bits_per_sample = format_data[i].bits_per_sample;
-          samples_per_pixel = format_data[i].samples_per_pixel;
-          sample_format = format_data[i].sample_format;
-          break;
-        }
-    }
-
-  if (bits_per_sample == 0)
-    {
-      /* An 8-bit format we don't have in the table, handle
-       * it by converting to R8G8B8A8_PREMULTIPLIED
-       */
-      stride = width * 4;
-      new_data = g_malloc (stride * height);
-      gdk_texture_download (memory_texture, new_data, stride);
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      flip_02 (new_data, width, height, stride);
-#endif
-      data = new_data;
-      bits_per_sample = 8;
-      samples_per_pixel = 4;
-      sample_format = SAMPLEFORMAT_UINT;
-    }
+  if (fdata == NULL)
+    fdata = &format_data[0];
 
   TIFFSetField (tif, TIFFTAG_SOFTWARE, "GTK");
   TIFFSetField (tif, TIFFTAG_IMAGEWIDTH, width);
   TIFFSetField (tif, TIFFTAG_IMAGELENGTH, height);
-  TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, bits_per_sample);
-  TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, samples_per_pixel);
-  TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, sample_format);
+  TIFFSetField (tif, TIFFTAG_BITSPERSAMPLE, fdata->bits_per_sample);
+  TIFFSetField (tif, TIFFTAG_SAMPLESPERPIXEL, fdata->samples_per_pixel);
+  TIFFSetField (tif, TIFFTAG_SAMPLEFORMAT, fdata->sample_format);
   TIFFSetField (tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
   TIFFSetField (tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
-  // TODO: save gamma / colorspace
-
-  if (samples_per_pixel > 3)
-    {
-      guint16 extra_samples[] = { EXTRASAMPLE_ASSOCALPHA };
-      TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, extra_samples);
-    }
+  if (fdata->alpha_samples)
+    TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, &fdata->alpha_samples);
 
   TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
   TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
 
+  memtex = gdk_memory_texture_from_texture (texture, fdata->format);
+  data = gdk_memory_texture_get_data (memtex);
+  stride = gdk_memory_texture_get_stride (memtex);
+
   line = (const guchar *)data;
   for (int y = 0; y < height; y++)
     {
       if (TIFFWriteScanline (tif, (void *)line, y, 0) == -1)
         {
           TIFFClose (tif);
-          g_free (new_data);
-          g_object_unref (memory_texture);
+          g_object_unref (memtex);
           return NULL;
         }
 
@@ -354,8 +314,7 @@ gdk_save_tiff (GdkTexture *texture)
 
   g_assert (result);
 
-  g_free (new_data);
-  g_object_unref (memory_texture);
+  g_object_unref (memtex);
 
   return result;
 }
@@ -407,6 +366,7 @@ gdk_load_tiff (GBytes  *input_bytes,
   guint16 sample_format;
   guint16 orientation;
   guint32 width, height;
+  guint16 alpha_samples;
   GdkMemoryFormat format;
   guchar *data, *line;
   gsize stride;
@@ -434,9 +394,10 @@ gdk_load_tiff (GBytes  *input_bytes,
       guint16 *extra_types;
 
       if (!TIFFGetField (tif, TIFFTAG_EXTRASAMPLES, &extra, &extra_types))
-        extra = 0;
+        alpha_samples = 0;
 
-      if (extra == 0 || extra_types[0] != EXTRASAMPLE_ASSOCALPHA)
+      alpha_samples = extra_types[0];
+      if (alpha_samples != 0 && alpha_samples != EXTRASAMPLE_ASSOCALPHA && alpha_samples != 
EXTRASAMPLE_UNASSALPHA)
         {
           texture = load_fallback (tif, error);
           TIFFClose (tif);
@@ -444,20 +405,22 @@ gdk_load_tiff (GBytes  *input_bytes,
         }
     }
 
-  format = 0;
-
-  for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
+  for (format = 0; format < G_N_ELEMENTS (format_data); format++)
     {
-      if (format_data[i].sample_format == sample_format &&
-          format_data[i].bits_per_sample == bits_per_sample &&
-          format_data[i].samples_per_pixel == samples_per_pixel)
+      /* not a native format */
+      if (format_data[format].format != format)
+        continue;
+
+      if (format_data[format].sample_format == sample_format &&
+          format_data[format].bits_per_sample == bits_per_sample &&
+          format_data[format].samples_per_pixel == samples_per_pixel &&
+          format_data[format].alpha_samples == alpha_samples)
         {
-          format = format_data[i].format;
           break;
         }
     }
 
-  if (format == 0 ||
+  if (format == G_N_ELEMENTS(format_data) ||
       photometric != PHOTOMETRIC_RGB ||
       planarconfig != PLANARCONFIG_CONTIG ||
       TIFFIsTiled (tif) ||


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