Update to patch (removed some unused code and an incorrect comment). 2009/4/13 Henrik Akesson <h.m.akesson@xxxxxxxxx>: > Hi, > > I've done a patch for reading and writing ppm images. This is mainly > meant for debugging and testing purposes, as (when using ascii format) > images can easily be diffed. > > [ppm.diff] > > Patch from Henrik Akesson that adds a portable pixmap loader and saver > that can read/write both the ascii and the binary formats. > > * operations/external/Makefile.am > * operations/external/ppm-load.c > * operations/external/ppm-save.c > > > /Henrik >
Index: operations/external/ppm-load.c =================================================================== --- operations/external/ppm-load.c (revision 0) +++ operations/external/ppm-load.c (revision 0) @@ -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 Index: operations/external/ppm-save.c =================================================================== --- operations/external/ppm-save.c (revision 0) +++ operations/external/ppm-save.c (revision 0) @@ -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 Index: operations/external/Makefile.am =================================================================== --- operations/external/Makefile.am (revision 3053) +++ operations/external/Makefile.am (working copy) @@ -2,7 +2,7 @@ # start out with no ops, each if/endif block contains all the bits relevant # for a specific dependency. -ops = +ops = ppm-load.la ppm-save.la if HAVE_PANGOCAIRO ops += text.la
_______________________________________________ Gegl-developer mailing list Gegl-developer@xxxxxxxxxxxxxxxxxxxxxx https://lists.XCF.Berkeley.EDU/mailman/listinfo/gegl-developer