[gegl] operations: Add gegl:ppm-load and gegl:ppm-save
- From: Martin Nordholts <martinn src gnome org>
- To: svn-commits-list gnome org
- Subject: [gegl] operations: Add gegl:ppm-load and gegl:ppm-save
- Date: Tue, 21 Apr 2009 13:40:18 -0400 (EDT)
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]