[gimp/metadata-browser] stab at the tiff plugin. Die! die! die!



commit c6fdb90ccc5f1d0496c1ee2da78a3f2f55133a3e
Author: Simon Budig <simon budig de>
Date:   Tue May 15 02:31:23 2012 +0200

    stab at the tiff plugin. Die! die! die!

 plug-ins/common/Makefile.am      |    1 +
 plug-ins/common/file-tiff-load.c |  290 +++++++++++++++++++++++++-------------
 plug-ins/common/plugin-defs.pl   |    2 +-
 3 files changed, 193 insertions(+), 100 deletions(-)
---
diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index 506abfa..084e3a6 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -1489,6 +1489,7 @@ file_tiff_load_LDADD = \
 	$(libgimpcolor)		\
 	$(libgimpbase)		\
 	$(GTK_LIBS)		\
+	$(GEGL_LIBS)		\
 	$(TIFF_LIBS)		\
 	$(RT_LIBS)		\
 	$(INTLLIBS)		\
diff --git a/plug-ins/common/file-tiff-load.c b/plug-ins/common/file-tiff-load.c
index ea93fe2..911ddbb 100644
--- a/plug-ins/common/file-tiff-load.c
+++ b/plug-ins/common/file-tiff-load.c
@@ -86,8 +86,8 @@ typedef struct
 typedef struct
 {
   gint32        ID;
-  GimpDrawable *drawable;
-  GimpPixelRgn  pixel_rgn;
+  GeglBuffer   *buffer;
+  const Babl   *format;
   guchar       *pixels;
   guchar       *pixel;
 } channel_data;
@@ -121,16 +121,12 @@ static void      load_rgba     (TIFF         *tif,
 static void      load_lines    (TIFF         *tif,
                                 channel_data *channel,
                                 gushort       bps,
-                                gushort       photomet,
-                                gboolean      alpha,
-                                gboolean      is_bw,
+                                gushort       spp,
                                 gint          extra);
 static void      load_tiles    (TIFF         *tif,
                                 channel_data *channel,
                                 gushort       bps,
-                                gushort       photomet,
-                                gboolean      alpha,
-                                gboolean      is_bw,
+                                gushort       spp,
                                 gint          extra);
 static void      load_paths    (TIFF         *tif,
                                 gint          image);
@@ -271,6 +267,8 @@ run (const gchar      *name,
   *nreturn_vals = 1;
   *return_vals  = values;
 
+  gegl_init (NULL, NULL);
+
   values[0].type          = GIMP_PDB_STATUS;
   values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
 
@@ -561,6 +559,7 @@ load_image (const gchar        *filename,
   gint          image = 0, image_type = GIMP_RGB;
   gint          layer, layer_type     = GIMP_RGB_IMAGE;
   gint          first_image_type      = GIMP_RGB;
+  const Babl   *base_format = NULL;
   float         layer_offset_x        = 0.0;
   float         layer_offset_y        = 0.0;
   gint          layer_offset_x_pixel  = 0;
@@ -578,7 +577,7 @@ load_image (const gchar        *filename,
 
   gboolean      is_bw;
 
-  gint          i, j;
+  gint          i;
   gboolean      worst_case = FALSE;
 
   TiffSaveVals  save_vals;
@@ -609,6 +608,8 @@ load_image (const gchar        *filename,
     {
       gint ilayer;
 
+      base_format = NULL;
+
       TIFFSetDirectory (tif, pages->pages[li]);
       ilayer = pages->pages[li];
 
@@ -710,6 +711,7 @@ load_image (const gchar        *filename,
         {
         case PHOTOMETRIC_MINISBLACK:
         case PHOTOMETRIC_MINISWHITE:
+#if 0
           if (bps == 1 && !alpha && spp == 1)
             {
               image_type = GIMP_INDEXED;
@@ -719,21 +721,40 @@ load_image (const gchar        *filename,
               fill_bit2byte ();
             }
           else
+#endif
             {
               image_type = GIMP_GRAY;
               layer_type = (alpha) ? GIMP_GRAYA_IMAGE : GIMP_GRAY_IMAGE;
+              if (bps == 8 && alpha)
+                base_format = babl_format ("Y u8");
+              else if (bps == 8 && !alpha)
+                base_format = babl_format ("Y u8");
+              else if (bps == 16 && alpha)
+                base_format = babl_format ("Y u16");
+              else if (bps == 16 && !alpha)
+                base_format = babl_format ("Y u16");
             }
           break;
 
         case PHOTOMETRIC_RGB:
           image_type = GIMP_RGB;
           layer_type = (alpha) ? GIMP_RGBA_IMAGE : GIMP_RGB_IMAGE;
+          if (bps == 8 && alpha)
+            base_format = babl_format ("R'G'B'A u8");
+          else if (bps == 8 && !alpha)
+            base_format = babl_format ("R'G'B' u8");
+          else if (bps == 16 && alpha)
+            base_format = babl_format ("R'G'B'A u16");
+          else if (bps == 16 && !alpha)
+            base_format = babl_format ("R'G'B' u16");
           break;
 
+#if 0
         case PHOTOMETRIC_PALETTE:
           image_type = GIMP_INDEXED;
           layer_type = (alpha) ? GIMP_INDEXEDA_IMAGE : GIMP_INDEXED_IMAGE;
           break;
+#endif
 
         default:
           worst_case = TRUE;
@@ -744,6 +765,10 @@ load_image (const gchar        *filename,
         {
           image_type = GIMP_RGB;
           layer_type = GIMP_RGBA_IMAGE;
+          if (bps == 8)
+            base_format = babl_format ("R'G'B'A u8");
+          else if (bps == 16)
+            base_format = babl_format ("R'G'B'A u16");
         }
 
       if (target == GIMP_PAGE_SELECTOR_TARGET_LAYERS)
@@ -756,7 +781,8 @@ load_image (const gchar        *filename,
 
       if ((target == GIMP_PAGE_SELECTOR_TARGET_IMAGES) || (! image))
         {
-          if ((image = gimp_image_new (cols, rows, image_type)) == -1)
+          if ((image = gimp_image_new_with_precision (cols, rows, image_type,
+                                                      bps <= 8 ? GIMP_PRECISION_U8 : GIMP_PRECISION_U16)) == -1)
             {
               g_message ("Could not create a new image: %s",
                          gimp_get_pdb_error ());
@@ -863,7 +889,6 @@ load_image (const gchar        *filename,
           {
             if (TIFFGetField (tif, TIFFTAG_YRESOLUTION, &yres))
               {
-
                 if (TIFFGetFieldDefaulted (tif, TIFFTAG_RESOLUTIONUNIT,
                                            &read_unit))
                   {
@@ -937,7 +962,7 @@ load_image (const gchar        *filename,
         layer_offset_y_pixel = ROUND(layer_offset_y * yres);
       }
 
-
+#if 0
       /* Install colormap for INDEXED images only */
       if (image_type == GIMP_INDEXED)
         {
@@ -974,6 +999,7 @@ load_image (const gchar        *filename,
 
           gimp_image_set_colormap (image, cmap, (1 << bps));
         }
+#endif
 
       load_paths (tif, image);
 
@@ -1004,8 +1030,9 @@ load_image (const gchar        *filename,
           g_free (name);
         }
 
-      channel[0].ID       = layer;
-      channel[0].drawable = gimp_drawable_get (layer);
+      channel[0].ID     = layer;
+      channel[0].buffer = gimp_drawable_get_buffer (layer);
+      channel[0].format = base_format;
 
       if (extra > 0 && !worst_case)
         {
@@ -1016,27 +1043,25 @@ load_image (const gchar        *filename,
                                                 cols, rows,
                                                 100.0, &color);
               gimp_image_insert_channel (image, channel[i].ID, -1, 0);
-              channel[i].drawable = gimp_drawable_get (channel[i].ID);
+              channel[i].buffer = gimp_drawable_get_buffer (channel[i].ID);
+              if (bps < 16)
+                channel[i].format = babl_format ("A u8");
+              else
+                channel[i].format = babl_format ("A u16");
             }
         }
 
-      if (bps == 16)
-        g_message (_("Warning:\n"
-                     "The image you are loading has 16 bits per channel. GIMP "
-                     "can only handle 8 bit, so it will be converted for you. "
-                     "Information will be lost because of this conversion."));
-
       if (worst_case)
         {
-          load_rgba (tif, channel);
+          // load_rgba (tif, channel);
         }
       else if (TIFFIsTiled (tif))
         {
-          load_tiles (tif, channel, bps, photomet, alpha, is_bw, extra);
+          load_tiles (tif, channel, bps, spp, extra);
         }
       else
         { /* Load scanlines in tile_height chunks */
-          load_lines (tif, channel, bps, photomet, alpha, is_bw, extra);
+          load_lines (tif, channel, bps, spp, extra);
         }
 
       if (TIFFGetField (tif, TIFFTAG_ORIENTATION, &orientation))
@@ -1079,13 +1104,9 @@ load_image (const gchar        *filename,
                                              -1.0 /*axis*/);
         }
 
-      gimp_drawable_flush (channel[0].drawable);
-      gimp_drawable_detach (channel[0].drawable);
-
-      for (i = 1; !worst_case && i < extra; ++i)
+      for (i = 0; i <= extra; ++i)
         {
-          gimp_drawable_flush (channel[i].drawable);
-          gimp_drawable_detach (channel[i].drawable);
+          g_object_unref (channel[i].buffer);
         }
 
       g_free (channel);
@@ -1161,6 +1182,7 @@ load_image (const gchar        *filename,
   return image;
 }
 
+#if 0
 static void
 load_rgba (TIFF         *tif,
            channel_data *channel)
@@ -1203,6 +1225,7 @@ load_rgba (TIFF         *tif,
         gimp_progress_update ((gdouble) row / (gdouble) imageLength);
     }
 }
+#endif
 
 static void
 load_paths (TIFF *tif, gint image)
@@ -1397,45 +1420,51 @@ static void
 load_tiles (TIFF         *tif,
             channel_data *channel,
             gushort       bps,
-            gushort       photomet,
-            gboolean      alpha,
-            gboolean      is_bw,
+            gushort       spp,
             gint          extra)
 {
   uint16  planar = PLANARCONFIG_CONTIG;
   uint32  imageWidth, imageLength;
   uint32  tileWidth, tileLength;
   uint32  x, y, rows, cols;
+  int bytes_per_pixel;
+  GeglBuffer *src_buf;
+  const Babl *src_format;
+  GeglBufferIterator *iter;
   guchar *buffer;
   gdouble progress = 0.0, one_row;
   gint    i;
 
+  g_printerr ("%s\n", __func__);
+
   TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
   TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
   TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
   TIFFGetField (tif, TIFFTAG_TILEWIDTH, &tileWidth);
   TIFFGetField (tif, TIFFTAG_TILELENGTH, &tileLength);
 
-  if (tileWidth > gimp_tile_width () || tileLength > gimp_tile_height ())
-    {
-      gimp_tile_cache_ntiles ((1 + tileWidth / gimp_tile_width ()) *
-                              (1 + tileLength / gimp_tile_width ()));
-    }
-
   one_row = (gdouble) tileLength / (gdouble) imageLength;
   buffer = g_malloc (TIFFTileSize (tif));
 
-  for (i = 0; i <= extra; ++i)
-    {
-      channel[i].pixels = g_new (guchar,
-                                 tileWidth * tileLength *
-                                 channel[i].drawable->bpp);
-    }
+  if (bps < 16)
+    src_format = babl_format_n (babl_type ("u8"), spp);
+  else
+    src_format = babl_format_n (babl_type ("u16"), spp);
+
+  /* consistency check */
+  bytes_per_pixel = 0;
+  for (i = 0; i <= extra; i++)
+    bytes_per_pixel += babl_format_get_bytes_per_pixel (channel[i].format);
+
+  g_printerr ("bytes_per_pixel: %d, format: %d\n", bytes_per_pixel,
+              babl_format_get_bytes_per_pixel (src_format));
 
   for (y = 0; y < imageLength; y += tileLength)
     {
       for (x = 0; x < imageWidth; x += tileWidth)
         {
+          int offset;
+
           gimp_progress_update (progress + one_row *
                                 ( (gdouble) x / (gdouble) imageWidth));
 
@@ -1444,71 +1473,100 @@ load_tiles (TIFF         *tif,
           cols = MIN (imageWidth - x, tileWidth);
           rows = MIN (imageLength - y, tileLength);
 
-          if (bps == 16)
-            {
-              read_16bit (buffer, channel, photomet, y, x, rows, cols, alpha,
-                          extra, tileWidth - cols);
-            }
-          else if (bps == 8)
-            {
-              read_8bit (buffer, channel, photomet, y, x, rows, cols, alpha,
-                         extra, tileWidth - cols);
-            }
-          else if (is_bw)
-            {
-              read_bw (buffer, channel, y, x, rows, cols, tileWidth - cols);
-            }
-          else
+          src_buf = gegl_buffer_linear_new_from_data (buffer,
+                                                      src_format,
+                                                      GEGL_RECTANGLE (0, 0, cols, rows),
+                                                      GEGL_AUTO_ROWSTRIDE,
+                                                      NULL, NULL);
+
+          offset = 0;
+
+          for (i = 0; i <= extra; i++)
             {
-              read_default (buffer, channel, bps, photomet, y, x, rows, cols,
-                            alpha, extra, tileWidth - cols);
+              int src_bpp, dest_bpp;
+
+              src_bpp = babl_format_get_bytes_per_pixel (src_format);
+              dest_bpp = babl_format_get_bytes_per_pixel (channel[i].format);
+
+              iter = gegl_buffer_iterator_new (src_buf, NULL, 0, NULL,
+                                               GEGL_BUFFER_READ,
+                                               GEGL_ABYSS_NONE);
+              gegl_buffer_iterator_add (iter, channel[i].buffer,
+                                        GEGL_RECTANGLE (x, y, cols, rows),
+                                        0, NULL,
+                                        GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  guchar *s = ((guchar *) iter->data[0]) + offset;
+                  guchar *d = iter->data[1];
+                  gint length = iter->length;
+
+                  while (length--)
+                    {
+                      memcpy (d, s, dest_bpp);
+                      d += dest_bpp;
+                      s += src_bpp;
+                    }
+                }
+
+              offset += dest_bpp;
             }
+
+          g_object_unref (src_buf);
         }
 
       progress += one_row;
     }
-
-  for (i = 0; i <= extra; ++i)
-    g_free(channel[i].pixels);
-
-  g_free(buffer);
 }
 
 static void
 load_lines (TIFF         *tif,
             channel_data *channel,
             gushort       bps,
-            gushort       photomet,
-            gboolean      alpha,
-            gboolean      is_bw,
+            gushort       spp,
             gint          extra)
 {
   uint16  planar = PLANARCONFIG_CONTIG;
-  uint32  imageLength, lineSize, cols, rows;
+  uint32  imageWidth, imageLength, lineSize, cols, rows;
+  int bytes_per_pixel;
+  GeglBuffer *src_buf;
+  const Babl *src_format;
+  GeglBufferIterator *iter;
   guchar *buffer;
   gint    i, y;
   gint    tile_height = gimp_tile_height ();
 
+  g_printerr ("%s\n", __func__);
+
   TIFFGetField (tif, TIFFTAG_PLANARCONFIG, &planar);
+  TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
   TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &imageLength);
   TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &cols);
 
   lineSize = TIFFScanlineSize (tif);
+  buffer = g_malloc (lineSize * tile_height);
 
-  for (i = 0; i <= extra; ++i)
-    {
-      channel[i].pixels = g_new (guchar,
-                                 tile_height * cols * channel[i].drawable->bpp);
-    }
+  if (bps < 16)
+    src_format = babl_format_n (babl_type ("u8"), spp);
+  else
+    src_format = babl_format_n (babl_type ("u16"), spp);
 
-  gimp_tile_cache_ntiles (1 + cols / gimp_tile_width ());
+  /* consistency check */
+  bytes_per_pixel = 0;
+  for (i = 0; i <= extra; i++)
+    bytes_per_pixel += babl_format_get_bytes_per_pixel (channel[i].format);
 
-  buffer = g_malloc (lineSize * tile_height);
+  g_printerr ("bytes_per_pixel: %d, format: %d\n", bytes_per_pixel,
+              babl_format_get_bytes_per_pixel (src_format));
 
   if (planar == PLANARCONFIG_CONTIG)
     {
-      for (y = 0; y < imageLength; y += tile_height )
+      for (y = 0; y < imageLength; y += tile_height)
         {
+          int offset;
+
+          g_printerr ("y: %d, th: %d, il: %d\n", y, tile_height, imageLength);
           gimp_progress_update ((gdouble) y / (gdouble) imageLength);
 
           rows = MIN (tile_height, imageLength - y);
@@ -1516,25 +1574,48 @@ load_lines (TIFF         *tif,
           for (i = 0; i < rows; ++i)
             TIFFReadScanline (tif, buffer + i * lineSize, y + i, 0);
 
-          if (bps == 16)
-            {
-              read_16bit (buffer, channel, photomet, y, 0, rows, cols,
-                          alpha, extra, 0);
-            }
-          else if (bps == 8)
-            {
-              read_8bit (buffer, channel, photomet, y, 0, rows, cols,
-                         alpha, extra, 0);
-            }
-          else if (is_bw)
-            {
-              read_bw (buffer, channel, y, 0, rows, cols, 0);
-            }
-          else
+          src_buf = gegl_buffer_linear_new_from_data (buffer,
+                                                      src_format,
+                                                      GEGL_RECTANGLE (0, 0, imageWidth, rows),
+                                                      GEGL_AUTO_ROWSTRIDE,
+                                                      NULL, NULL);
+
+          offset = 0;
+
+          for (i = 0; i <= extra; i++)
             {
-              read_default (buffer, channel, bps, photomet, y, 0, rows, cols,
-                            alpha, extra, 0);
+              int src_bpp, dest_bpp;
+
+              src_bpp = babl_format_get_bytes_per_pixel (src_format);
+              dest_bpp = babl_format_get_bytes_per_pixel (channel[i].format);
+
+              iter = gegl_buffer_iterator_new (src_buf, NULL, 0, NULL,
+                                               GEGL_BUFFER_READ,
+                                               GEGL_ABYSS_NONE);
+              gegl_buffer_iterator_add (iter, channel[i].buffer,
+                                        GEGL_RECTANGLE (0, y, imageWidth, rows),
+                                        0, NULL,
+                                        GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
+
+              while (gegl_buffer_iterator_next (iter))
+                {
+                  guchar *s = ((guchar *) iter->data[0]) + offset;
+                  guchar *d = iter->data[1];
+                  gint length = iter->length;
+
+                  while (length--)
+                    {
+                      memcpy (d, s, dest_bpp);
+                      d += dest_bpp;
+                      s += src_bpp;
+                    }
+                }
+
+              offset += dest_bpp;
+              gegl_buffer_flush (channel[i].buffer);
             }
+
+          g_object_unref (src_buf);
         }
     }
   else
@@ -1543,6 +1624,9 @@ load_lines (TIFF         *tif,
 
       TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples);
 
+      g_printerr ("PLANARCONFIG_SEPARATE unsupported for now\n");
+
+#if 0
       for (s = 0; s < samples; ++s)
         {
           for (y = 0; y < imageLength; y += tile_height )
@@ -1557,14 +1641,13 @@ load_lines (TIFF         *tif,
                              y, 0, rows, cols, alpha, extra, s);
             }
         }
+#endif
     }
 
-  for (i = 0; i <= extra; ++i)
-    g_free(channel[i].pixels);
-
   g_free(buffer);
 }
 
+#if 0
 static void
 read_16bit (const guchar *source,
             channel_data *channel,
@@ -1736,7 +1819,9 @@ read_16bit (const guchar *source,
     gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
                              startcol, startrow, cols, rows);
 }
+#endif
 
+#if 0
 static void
 read_8bit (const guchar *source,
            channel_data *channel,
@@ -1901,7 +1986,9 @@ read_8bit (const guchar *source,
     gimp_pixel_rgn_set_rect(&(channel[i].pixel_rgn), channel[i].pixels,
                             startcol, startrow, cols, rows);
 }
+#endif
 
+#if 0
 static void
 read_bw (const guchar *source,
          channel_data *channel,
@@ -1944,6 +2031,7 @@ read_bw (const guchar *source,
   gimp_pixel_rgn_set_rect(&(channel[0].pixel_rgn), channel[0].pixels,
                           startcol, startrow, cols, rows);
 }
+#endif
 
 /* Step through all <= 8-bit samples in an image */
 
@@ -1958,6 +2046,7 @@ read_bw (const guchar *source,
       var = ( *source >> bitsleft ) & maxval; \
   }
 
+#if 0
 static void
 read_default (const guchar *source,
               channel_data *channel,
@@ -2137,7 +2226,9 @@ read_default (const guchar *source,
     gimp_pixel_rgn_set_rect (&(channel[i].pixel_rgn), channel[i].pixels,
                              startcol, startrow, cols, rows);
 }
+#endif
 
+#if 0
 static void
 read_separate (const guchar *source,
                channel_data *channel,
@@ -2190,6 +2281,7 @@ read_separate (const guchar *source,
   gimp_pixel_rgn_set_rect (&(channel[c].pixel_rgn), channel[c].pixels,
                            startcol, startrow, cols, rows);
 }
+#endif
 
 static void
 fill_bit2byte(void)
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index 3bae369..d76595b 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -73,7 +73,7 @@
     'file-sunras' => { ui => 1 },
     'file-svg' => { ui => 1, optional => 1, libs => 'SVG_LIBS', cflags => 'SVG_CFLAGS' },
     'file-tga' => { ui => 1 },
-    'file-tiff-load' => { ui => 1, optional => 1, libs => 'TIFF_LIBS' },
+    'file-tiff-load' => { ui => 1, gegl => 1, optional => 1, libs => 'TIFF_LIBS' },
     'file-tiff-save' => { ui => 1, optional => 1, libs => 'TIFF_LIBS' },
     'file-wmf' => { ui => 1, optional => 1, libs => 'WMF_LIBS', cflags => 'WMF_CFLAGS' },
     'file-xbm' => { ui => 1 },



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