[gimp] first shot at PNG loading with GEGL



commit 5edf1b1972926ec2a1d103dc6557c4ea961e52f5
Author: Simon Budig <simon budig de>
Date:   Thu Apr 26 03:16:19 2012 +0200

    first shot at PNG loading with GEGL
    
    Doesn't work yet for 16bit PNGs, there is a weird crash in libgimp
    but I didn't do anything...
    
    This closely follows the old pixel region based code, which might
    be suboptimal for gegl, but has the advantage of keeping metadata intact.
    
    Indexed currently is disabled, needs resurrecting.

 plug-ins/common/Makefile.am    |    1 +
 plug-ins/common/file-png.c     |   79 ++++++++++++++++++----------------------
 plug-ins/common/plugin-defs.pl |    2 +-
 3 files changed, 37 insertions(+), 45 deletions(-)
---
diff --git a/plug-ins/common/Makefile.am b/plug-ins/common/Makefile.am
index cf3dd2e..d5d7712 100644
--- a/plug-ins/common/Makefile.am
+++ b/plug-ins/common/Makefile.am
@@ -1330,6 +1330,7 @@ file_png_LDADD = \
 	$(libgimpcolor)		\
 	$(libgimpbase)		\
 	$(GTK_LIBS)		\
+	$(GEGL_LIBS)		\
 	$(PNG_LIBS)		\
 	$(RT_LIBS)		\
 	$(INTLLIBS)		\
diff --git a/plug-ins/common/file-png.c b/plug-ins/common/file-png.c
index 4e590a9..3ee6733 100644
--- a/plug-ins/common/file-png.c
+++ b/plug-ins/common/file-png.c
@@ -411,6 +411,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;
 
@@ -621,9 +623,9 @@ run (const gchar      *name,
 
 struct read_error_data
 {
-  GimpPixelRgn *pixel_rgn;       /* Pixel region for layer */
   guchar       *pixel;           /* Pixel data */
-  GimpDrawable *drawable;        /* Drawable for layer */
+  GeglBuffer   *buffer;          /* GEGL buffer for layer */
+  const Babl   *file_format;
   guint32       width;           /* png_infop->width */
   guint32       height;          /* png_infop->height */
   gint          bpp;             /* Bytes per pixel */
@@ -645,9 +647,7 @@ on_read_error (png_structp png_ptr, png_const_charp error_msg)
 
   /* Flush the current half-read row of tiles */
 
-  gimp_pixel_rgn_set_rect (error_data->pixel_rgn, error_data->pixel, 0,
-                                error_data->begin, error_data->drawable->width,
-                                error_data->num);
+  gegl_buffer_set (error_data->buffer, GEGL_RECTANGLE (0, error_data->begin, gegl_buffer_get_width (error_data->buffer), error_data->num), 0, error_data->file_format, error_data->pixel, GEGL_AUTO_ROWSTRIDE);
 
   /* Fill the rest of the rows of tiles with 0s */
 
@@ -664,9 +664,7 @@ on_read_error (png_structp png_ptr, png_const_charp error_msg)
 
       num = end - begin;
 
-      gimp_pixel_rgn_set_rect (error_data->pixel_rgn, error_data->pixel, 0,
-                                begin,
-                                error_data->drawable->width, num);
+      gegl_buffer_set (error_data->buffer, GEGL_RECTANGLE (0, begin, gegl_buffer_get_width (error_data->buffer), num), 0, error_data->file_format, error_data->pixel, GEGL_AUTO_ROWSTRIDE);
     }
 
   longjmp (png_jmpbuf (png_ptr), 1);
@@ -696,6 +694,7 @@ load_image (const gchar  *filename,
   int i,                        /* Looping var */
     trns,                       /* Transparency present */
     bpp,                        /* Bytes per pixel */
+    have_u16 = 0,               /* 16bit values? */
     image_type,                 /* Type of image */
     layer_type,                 /* Type of drawable/layer */
     empty,                      /* Number of fully transparent indices */
@@ -708,8 +707,8 @@ load_image (const gchar  *filename,
   FILE *fp;                     /* File pointer */
   volatile gint32 image = -1;   /* Image -- preserved against setjmp() */
   gint32 layer;                 /* Layer */
-  GimpDrawable *drawable;       /* Drawable for layer */
-  GimpPixelRgn pixel_rgn;       /* Pixel region for layer */
+  GeglBuffer *buffer;           /* GEGL buffer for layer */
+  const Babl *file_format;      /* BABL format for layer */
   png_structp pp;               /* PNG read pointer */
   png_infop info;               /* PNG info pointers */
   guchar **pixels,              /* Pixel rows */
@@ -775,7 +774,8 @@ load_image (const gchar  *filename,
 
   if (png_get_bit_depth (pp, info) == 16)
     {
-      png_set_strip_16 (pp);
+      png_set_swap (pp);
+      have_u16 = 1;
     }
 
   if (png_get_color_type (pp, info) == PNG_COLOR_TYPE_GRAY &&
@@ -837,34 +837,41 @@ load_image (const gchar  *filename,
   switch (png_get_color_type (pp, info))
     {
     case PNG_COLOR_TYPE_RGB:           /* RGB */
-      bpp = 3;
       image_type = GIMP_RGB;
       layer_type = GIMP_RGB_IMAGE;
+      bpp = have_u16 ? 6 : 3;
+      file_format = babl_format (have_u16 ? "R'G'B' u16" : "R'G'B' u8");
       break;
 
     case PNG_COLOR_TYPE_RGB_ALPHA:     /* RGBA */
-      bpp = 4;
       image_type = GIMP_RGB;
       layer_type = GIMP_RGBA_IMAGE;
+      bpp = have_u16 ? 8 : 4;
+      file_format = babl_format (have_u16 ? "R'G'B'A u16" : "R'G'B'A u8");
       break;
 
     case PNG_COLOR_TYPE_GRAY:          /* Grayscale */
-      bpp = 1;
       image_type = GIMP_GRAY;
       layer_type = GIMP_GRAY_IMAGE;
+      bpp = have_u16 ? 2 : 1;
+      file_format = babl_format (have_u16 ? "Y' u16" : "Y' u8");
       break;
 
     case PNG_COLOR_TYPE_GRAY_ALPHA:    /* Grayscale + alpha */
-      bpp = 2;
       image_type = GIMP_GRAY;
       layer_type = GIMP_GRAYA_IMAGE;
+      bpp = have_u16 ? 4 : 2;
+      file_format = babl_format (have_u16 ? "Y'A u16" : "Y'A u8");
       break;
 
+#warning port PNG indexed format
+#if 0
     case PNG_COLOR_TYPE_PALETTE:       /* Indexed */
       bpp = 1;
       image_type = GIMP_INDEXED;
       layer_type = GIMP_INDEXED_IMAGE;
       break;
+#endif
 
     default:                           /* Aie! Unknown type */
       g_set_error (error, 0, 0,
@@ -873,9 +880,10 @@ load_image (const gchar  *filename,
       return -1;
     }
 
-  image = gimp_image_new (png_get_image_width (pp, info),
-                          png_get_image_height (pp, info),
-                          image_type);
+  image = gimp_image_new_with_precision (png_get_image_width (pp, info),
+                                         png_get_image_height (pp, info),
+                                         image_type,
+                                         have_u16 ? GIMP_PRECISION_U16 : GIMP_PRECISION_U8);
   if (image == -1)
     {
       g_set_error (error, 0, 0,
@@ -1010,14 +1018,7 @@ load_image (const gchar  *filename,
         }
     }
 
-  /*
-   * Get the drawable and set the pixel region for our load...
-   */
-
-  drawable = gimp_drawable_get (layer);
-
-  gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0, drawable->width,
-                       drawable->height, TRUE, FALSE);
+  buffer = gimp_drawable_get_buffer (layer);
 
   /*
    * Temporary buffer...
@@ -1028,17 +1029,16 @@ load_image (const gchar  *filename,
   pixels = g_new (guchar *, tile_height);
 
   for (i = 0; i < tile_height; i++)
-    pixels[i] = pixel + png_get_image_width (pp, info) *
-      png_get_channels (pp, info) * i;
+    pixels[i] = pixel + png_get_image_width (pp, info) * bpp * i;
 
   /* Install our own error handler to handle incomplete PNG files better */
-  error_data.drawable    = drawable;
+  error_data.buffer      = buffer;
   error_data.pixel       = pixel;
+  error_data.file_format = file_format;
   error_data.tile_height = tile_height;
   error_data.width       = png_get_image_width (pp, info);
   error_data.height      = png_get_image_height (pp, info);
   error_data.bpp         = bpp;
-  error_data.pixel_rgn   = &pixel_rgn;
 
   png_set_error_fn (pp, &error_data, on_read_error, NULL);
 
@@ -1058,8 +1058,7 @@ load_image (const gchar  *filename,
           num = end - begin;
 
           if (pass != 0)        /* to handle interlaced PiNGs */
-            gimp_pixel_rgn_get_rect (&pixel_rgn, pixel, 0, begin,
-                                     drawable->width, num);
+            gegl_buffer_get (buffer, GEGL_RECTANGLE (0, begin, png_get_image_width (pp, info), num), 1.0, file_format, pixel, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
 
           error_data.begin = begin;
           error_data.end   = end;
@@ -1067,11 +1066,7 @@ load_image (const gchar  *filename,
 
           png_read_rows (pp, pixels, NULL, num);
 
-          gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, begin,
-                                   drawable->width, num);
-
-          memset (pixel, 0,
-                  tile_height * png_get_image_width (pp, info) * bpp);
+          gegl_buffer_set (buffer, GEGL_RECTANGLE (0, begin, png_get_image_width (pp, info), num), 0, file_format, pixel, GEGL_AUTO_ROWSTRIDE);
 
           gimp_progress_update
             (((gdouble) pass +
@@ -1172,11 +1167,13 @@ load_image (const gchar  *filename,
 
   g_free (pixel);
   g_free (pixels);
+  g_object_unref (buffer);
   free (pp);
   free (info);
 
   fclose (fp);
 
+#if 0
   if (trns)
     {
       gimp_layer_add_alpha (layer);
@@ -1208,13 +1205,7 @@ load_image (const gchar  *filename,
 
       g_free (pixel);
     }
-
-  /*
-   * Update the display...
-   */
-
-  gimp_drawable_flush (drawable);
-  gimp_drawable_detach (drawable);
+#endif
 
   return image;
 }
diff --git a/plug-ins/common/plugin-defs.pl b/plug-ins/common/plugin-defs.pl
index 3d842aa..b40a8a6 100644
--- a/plug-ins/common/plugin-defs.pl
+++ b/plug-ins/common/plugin-defs.pl
@@ -62,7 +62,7 @@
     'file-pat' => { ui => 1, gegl => 1 },
     'file-pcx' => { ui => 1 },
     'file-pix' => { ui => 1 },
-    'file-png' => { ui => 1, optional => 1, libs => 'PNG_LIBS', cflags => 'PNG_CFLAGS' },
+    'file-png' => { ui => 1, gegl => 1, optional => 1, libs => 'PNG_LIBS', cflags => 'PNG_CFLAGS' },
     'file-pnm' => { ui => 1 },
     'file-pdf-load' => { ui => 1, optional => 1, libs => 'POPPLER_LIBS', cflags => 'POPPLER_CFLAGS' },
     'file-pdf-save' => { ui => 1, optional => 1, libs => 'CAIRO_PDF_LIBS', cflags => 'CAIRO_PDF_CFLAGS' },



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