[gegl] operations: Add gegl:ppm-load and gegl:ppm-save



commit 5e6245cd0c50237a0d35086a6e7b6eccd6700940
Author: Henrik Akesson <h m akesson gmail com>
Date:   Tue Apr 21 19:13:09 2009 +0200

    operations: Add gegl:ppm-load and gegl:ppm-save
    
    Add a portable pixmap loader and saver that can read/write both the
    ascii and the binary formats.
---
 ChangeLog                       |   11 ++
 operations/external/Makefile.am |    3 +
 operations/external/ppm-load.c  |  219 +++++++++++++++++++++++++++++++++++++++
 operations/external/ppm-save.c  |  141 +++++++++++++++++++++++++
 4 files changed, 374 insertions(+), 0 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 270961d..11b31bb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-04-21  Martin Nordholts  <martinn svn gnome org>
 
+	Add a portable pixmap loader and saver that can read/write both
+	the ascii and the binary formats.
+
+	Patch from Henrik Akesson.
+
+	* operations/external/Makefile.am
+	* operations/external/ppm-load.c
+	* operations/external/ppm-save.c
+
+2009-04-21  Martin Nordholts  <martinn svn gnome org>
+
 	* operations/affine/affine.c: Make sure the sampler is initialized
 	before executing logic in get_bounding_box(). This feels like a
 	hack but should work fine for now.
diff --git a/operations/external/Makefile.am b/operations/external/Makefile.am
index 2a3a175..3f7f31b 100644
--- a/operations/external/Makefile.am
+++ b/operations/external/Makefile.am
@@ -79,5 +79,8 @@ ff_load_la_LIBADD = $(op_libs) $(AVFORMAT_LIBS)
 ff_load_la_CFLAGS = $(AM_CFLAGS) $(AVFORMAT_CFLAGS)
 endif
 
+# No dependencies
+ops += ppm-load.la ppm-save.la
+
 opdir = $(libdir)/gegl- GEGL_API_VERSION@
 op_LTLIBRARIES = $(ops)
diff --git a/operations/external/ppm-load.c b/operations/external/ppm-load.c
new file mode 100644
index 0000000..045f387
--- /dev/null
+++ b/operations/external/ppm-load.c
@@ -0,0 +1,219 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2009 Henrik Akesson <h.m.akesson (a) gmail.com>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_file_path (path, _("File"), "", _("Path of file to load."))
+
+#else
+
+#define GEGL_CHANT_TYPE_SOURCE
+#define GEGL_CHANT_C_FILE       "ppm-load.c"
+        
+#define MAX_CHARS_IN_ROW        500
+#define CHANNEL_COUNT           3
+#define ASCII_P                 80
+        
+#include "gegl-chant.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+typedef enum {
+  PIXMAP_ASCII  = 51,
+  PIXMAP_RAW    = 54,
+} map_type;
+
+typedef struct {
+	map_type   type;
+	gint       width;
+	gint       height;
+        gint       size;
+	gint       maxval;
+	guchar    *data;
+} pnm_struct;
+
+void
+ppm_load_read_header(FILE       *fp,
+                     pnm_struct *img);
+void
+ppm_load_read_image(FILE       *fp,
+                    pnm_struct *img);
+
+void
+ppm_load_read_header(FILE       *fp,
+                     pnm_struct *img)
+  {
+    /* PPM Headers Variable Declaration */
+    gchar *ptr;
+    gchar *retval;
+    gchar  header[MAX_CHARS_IN_ROW];
+
+    /* Check the PPM file Type P2 or P5 */
+    retval = fgets (header,MAX_CHARS_IN_ROW,fp);
+
+    if (header[0] != ASCII_P ||
+        (header[1] != PIXMAP_ASCII && 
+         header[1] != PIXMAP_RAW
+        )
+       )
+      printf ("Image is not a portable pixmap\n");
+
+    img->type = header[1];
+
+    /* Check the Comments */
+    retval = fgets (header,MAX_CHARS_IN_ROW,fp);
+    while(header[0] == '#')
+      {
+        retval = fgets (header,MAX_CHARS_IN_ROW,fp);
+      }
+
+    /* Get Width and Height */
+    img->width  = strtol (header,&ptr,0);
+    img->height = atoi (ptr);
+
+    img->size = img->width * img->height * sizeof (guchar) * CHANNEL_COUNT;
+
+    retval = fgets (header,100,fp);
+    /* Maxval is not used */
+    img->maxval = (int) strtol (header,&ptr,0);
+  }
+
+void
+ppm_load_read_image(FILE       *fp,
+                    pnm_struct *img)
+ {
+    gint    i;
+    gint    retval;
+    guchar *ptr;
+
+    if (img->type == PIXMAP_RAW)
+      {
+        /* Pixel Extraction */
+        retval = fread (img->data, 1, img->size, fp);
+      }
+    else
+      {
+        ptr = img->data;
+
+        for (i=0; i<img->size; i++)
+          retval = fscanf (fp, " %d", (int *) ptr++);
+      }
+  }
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+  GeglChantO   *o = GEGL_CHANT_PROPERTIES (operation);
+  GeglRectangle result = {0,0,0,0};
+  pnm_struct    img;
+  FILE         *fp;
+
+  fp = (!strcmp (o->path, "-") ? stdin : fopen (o->path,"rb") );
+
+  if (!fp)
+    {
+      return result;
+    }
+  ppm_load_read_header (fp, &img);
+
+  if (stdin != fp)
+    {
+      fclose (fp);
+    }
+
+  gegl_operation_set_format (operation, "output", babl_format ("R'G'B' u8"));
+
+  result.width  = img.width;
+  result.height  = img.height;
+
+  return result;
+}
+
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *output,
+         const GeglRectangle *result)
+{
+  GeglChantO   *o = GEGL_CHANT_PROPERTIES (operation);
+  FILE         *fp;
+  pnm_struct    img;
+  GeglRectangle rect = {0,0,0,0};
+
+  fp = (!strcmp (o->path, "-") ? stdin : fopen (o->path,"rb"));
+
+  if (!fp)
+    {
+      return FALSE;
+    }
+
+  ppm_load_read_header (fp, &img);
+  rect.height = img.height;
+  rect.width = img.width;
+
+  /* Allocating Array Size */
+  img.data = (guchar*) g_malloc0 (img.size);
+
+  gegl_buffer_get (output, 1.0, &rect, babl_format ("R'G'B' u8"), img.data,
+          GEGL_AUTO_ROWSTRIDE);
+
+  ppm_load_read_image (fp, &img);
+
+  gegl_buffer_set (output, &rect, babl_format ("R'G'B' u8"), img.data,
+          GEGL_AUTO_ROWSTRIDE);
+
+  g_free (img.data);
+  if (stdin != fp)
+    {
+      fclose (fp);
+    }
+  return  TRUE;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation       *operation,
+                   const GeglRectangle *roi)
+{
+  return get_bounding_box (operation);
+}
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+  GeglOperationClass       *operation_class;
+  GeglOperationSourceClass *source_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  source_class    = GEGL_OPERATION_SOURCE_CLASS (klass);
+
+  source_class->process = process;
+  operation_class->get_bounding_box = get_bounding_box;
+  operation_class->get_cached_region = get_cached_region;
+
+  operation_class->name        = "gegl:ppm-load";
+  operation_class->categories  = "hidden";
+  operation_class->description = _("PPM image loader.");
+
+  gegl_extension_handler_register (".ppm", "gegl:ppm-load");
+  gegl_extension_handler_register (".PPM", "gegl:ppm-load");
+}
+
+#endif
diff --git a/operations/external/ppm-save.c b/operations/external/ppm-save.c
new file mode 100644
index 0000000..1b574b1
--- /dev/null
+++ b/operations/external/ppm-save.c
@@ -0,0 +1,141 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright 2009 Henrik Akesson <h.m.akesson (a) gmail.com>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_string  (path, _("File"), "",
+                    _("Target path and filename, use '-' for stdout."))
+gegl_chant_boolean (rawformat, _("Raw format"), FALSE, _("Raw format"))
+
+#else
+
+#define GEGL_CHANT_TYPE_SINK
+#define GEGL_CHANT_C_FILE       "ppm-save.c"
+        
+#define CHANNEL_COUNT           3
+
+#include "gegl-chant.h"
+#include <stdio.h>
+
+typedef enum {
+  PIXMAP_ASCII  = 51,
+  PIXMAP_RAW    = 54,
+} map_type;
+
+void
+ppm_save_write(FILE     *fp,
+               gint      width,
+               gint      height,
+               guchar   *pixels,
+               map_type  type);
+
+void
+ppm_save_write(FILE    *fp,
+               gint     width,
+               gint     height,
+               guchar  *pixels,
+               map_type type)
+{
+  gint i, size, written;
+  guchar * ptr;
+
+  /* Write the header */
+  fprintf (fp, "P%c\n%d %d\n", type, width, height );
+  /* For the moment only 8 bit channels are supported */
+  fprintf (fp, "%d\n", 255);
+
+  size = width * height * sizeof (guchar) * CHANNEL_COUNT;
+
+  /* Raw images writes the data in binary form */
+  if (type == PIXMAP_RAW)
+    {
+      written = fwrite (pixels, 1, size, fp);
+    }
+  /* Otherwise a plain ascii format is used */
+  else
+    {
+      ptr = pixels;
+
+      for (i=0; i<size; i++)
+        {
+          fprintf (fp, "%3d ", (int) *ptr++);
+          if ((i + 1) % (width * CHANNEL_COUNT) == 0)
+            fprintf (fp, "\n");
+        }
+    }
+}
+
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         const GeglRectangle *rect)
+{
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+
+  FILE     *fp;
+  guchar   *pixels;
+  map_type  type;
+
+  fp = (!strcmp (o->path, "-") ? stdout : fopen(o->path, "wb") );
+  if (!fp)
+    {
+      return FALSE;
+    }
+
+  pixels = g_malloc0 (rect->width * rect->height * 3);
+  gegl_buffer_get (input, 1.0, rect, babl_format ("R'G'B' u8"), pixels,
+          GEGL_AUTO_ROWSTRIDE);
+
+  type = (o->rawformat ? PIXMAP_RAW : PIXMAP_ASCII);
+
+  ppm_save_write (fp, rect->width, rect->height, pixels, type);
+
+  g_free (pixels);
+  if (fp != stdout)
+    {
+      fclose( fp );
+    }
+
+  return  TRUE;
+}
+
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+  GeglOperationClass     *operation_class;
+  GeglOperationSinkClass *sink_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  sink_class      = GEGL_OPERATION_SINK_CLASS (klass);
+
+  sink_class->process = process;
+  sink_class->needs_full = TRUE;
+
+  operation_class->name        = "gegl:ppm-save";
+  operation_class->categories  = "output";
+  operation_class->description =
+        _("PPM image saver (Portable pixmap saver.)");
+
+}
+
+#endif



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