In my efforts to learn gegl, I extended the load-ppm.c operation to support PGM files.Â
On my todo list is next to create a npy save file operation, to make it easy to examine floating point gray level images in numpy.
diff --git a/operations/external/ppm-load.c b/operations/external/ppm-load.c
index e22521c..3b25438 100644
--- a/operations/external/ppm-load.c
+++ b/operations/external/ppm-load.c
@@ -31,7 +31,8 @@ gegl_chant_file_path (path, _("File"), "", _("Path of file to load."))
Â
 #define MAX_CHARS_IN_ROW     500
 #define CHANNEL_COUNT      3
-#define ASCII_P Â Â Â Â Â Â Â Â 80
+#define CHANNEL_COUNT_GRAY Â Â Â 1
+#define ASCII_P Â Â Â Â Â Â Â Â 'P'
Â
 #include "gegl-chant.h"
 #include <stdio.h>
@@ -39,8 +40,10 @@ gegl_chant_file_path (path, _("File"), "", _("Path of file to load."))
 #include <errno.h>
Â
 typedef enum {
- Â PIXMAP_ASCII Â = 51,
- Â PIXMAP_RAW Â Â = 54,
+ Â PIXMAP_ASCII_GRAY = '2',
+ Â PIXMAP_ASCII Â Â Â = '3',
+ Â PIXMAP_RAW_GRAY Â = '5',
+ Â PIXMAP_RAW Â Â Â Â = '6',
 } map_type;
Â
 typedef struct {
@@ -61,12 +64,15 @@ ppm_load_read_header(FILE Â Â Â *fp,
   //gchar *retval;
   gchar  header[MAX_CHARS_IN_ROW];
   gint  maxval;
+   int   channel_count;
Â
   /* Check the PPM file Type P3 or P6 */
   fgets (header,MAX_CHARS_IN_ROW,fp);
Â
   if (header[0] != ASCII_P ||
- Â Â Â Â (header[1] != PIXMAP_ASCII &&
+ Â Â Â Â (header[1] != PIXMAP_ASCII_GRAY &&
+ Â Â Â Â header[1] != PIXMAP_ASCII &&
+ Â Â Â Â header[1] != PIXMAP_RAW_GRAY &&
     header[1] != PIXMAP_RAW))
    {
     g_warning ("Image is not a portable pixmap");
@@ -75,6 +81,11 @@ ppm_load_read_header(FILE Â Â Â *fp,
Â
   img->type = header[1];
Â
+ Â Â if (img->type == PIXMAP_ASCII_GRAY || img->type == PIXMAP_ASCII_GRAY)
+ Â Â Â channel_count = CHANNEL_COUNT_GRAY;
+ Â Â else
+ Â Â Â channel_count = CHANNEL_COUNT;
+
   /* Check the Comments */
   fgets (header,MAX_CHARS_IN_ROW,fp);
   while(header[0] == '#')
@@ -139,7 +150,9 @@ ppm_load_read_header(FILE Â Â Â *fp,
     g_warning ("Illegal width/height: %ld/%ld", img->width, img->height);
     return FALSE;
    }
- Â Â img->numsamples = img->width * img->height * CHANNEL_COUNT;
+
+
+ Â Â img->numsamples = img->width * img->height * channel_count;
Â
   return TRUE;
 }
@@ -150,7 +163,7 @@ ppm_load_read_image(FILE Â Â Â *fp,
 {
   guint  i;
Â
- Â Â if (img->type == PIXMAP_RAW)
+ Â Â if (img->type == PIXMAP_RAW || img->type == PIXMAP_RAW_GRAY)
    {
     fread (img->data, img->bpc, img->numsamples, fp);
Â
@@ -168,7 +181,7 @@ ppm_load_read_image(FILE Â Â Â *fp,
    }
   else
    {
- Â Â Â Â /* Plain PPM format */
+ Â Â Â Â /* Plain PPM or PGM format */
Â
     if (img->bpc == sizeof (guchar))
      {
@@ -215,21 +228,26 @@ get_bounding_box (GeglOperation *operation)
  if (!ppm_load_read_header (fp, &img))
   goto out;
Â
- Â switch (img.bpc)
+ Â if (img.bpc == 1)
   {
- Â Â case 1:
+ Â Â Â if (img.numsamples == 3)
     gegl_operation_set_format (operation, "output",
                  babl_format ("R'G'B' u8"));
- Â Â Â break;
-
- Â Â case 2:
+ Â Â Â else
+ Â Â Â Â gegl_operation_set_format (operation, "output",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â babl_format ("Y' u8"));
+ Â Â }
+ Â else if (img.bpc == 2)
+ Â Â {
+ Â Â Â if (img.numsamples == 3)
     gegl_operation_set_format (operation, "output",
                  babl_format ("R'G'B' u16"));
- Â Â Â break;
-
- Â Â default:
- Â Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
+ Â Â Â else
+ Â Â Â Â gegl_operation_set_format (operation, "output",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â babl_format ("Y' u8"));
   }
+ Â else
+ Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
Â
  result.width = img.width;
  result.height = img.height;
@@ -279,39 +297,49 @@ process (GeglOperation    *operation,
  rect.height = img.height;
  rect.width = img.width;
Â
- Â switch (img.bpc)
+ Â if (img.bpc == 1)
   {
- Â Â case 1:
+ Â Â Â if (img.numsamples == 3)
     gegl_buffer_get (output, &rect, 1.0, babl_format ("R'G'B' u8"), img.data,
             GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- Â Â Â break;
-
- Â Â case 2:
+ Â Â Â else
+ Â Â Â Â gegl_buffer_get (output, &rect, 1.0, babl_format ("Y' u8"), img.data,
+ Â Â Â Â Â Â Â Â Â Â Â Â GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+ Â Â }
+ Â else if (img.bpc == 2)
+ Â Â {
+ Â Â Â if (img.numsamples == 3)
     gegl_buffer_get (output, &rect, 1.0, babl_format ("R'G'B' u16"), img.data,
             GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
- Â Â Â break;
-
- Â Â default:
- Â Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
+ Â Â Â else
+ Â Â Â Â gegl_buffer_get (output, &rect, 1.0, babl_format ("Y' u16"), img.data,
+ Â Â Â Â Â Â Â Â Â Â Â Â GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
   }
+ Â else
+ Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
Â
  ppm_load_read_image (fp, &img);
Â
- Â switch (img.bpc)
+ Â if (img.bpc == 1)
   {
- Â Â case 1:
+ Â Â Â if (img.numsamples == 3)
     gegl_buffer_set (output, &rect, 0, babl_format ("R'G'B' u8"), img.data,
             GEGL_AUTO_ROWSTRIDE);
- Â Â Â break;
-
- Â Â case 2:
+ Â Â Â else
+ Â Â Â Â gegl_buffer_set (output, &rect, 0, babl_format ("Y' u8"), img.data,
+ Â Â Â Â Â Â Â Â Â Â Â Â GEGL_AUTO_ROWSTRIDE);
+ Â Â }
+ Â else if (img.bpc == 2)
+ Â Â {
+ Â Â Â if (img.numsamples == 3)
     gegl_buffer_set (output, &rect, 0, babl_format ("R'G'B' u16"), img.data,
             GEGL_AUTO_ROWSTRIDE);
- Â Â Â break;
-
- Â Â default:
- Â Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
+ Â Â Â else
+ Â Â Â Â gegl_buffer_set (output, &rect, 0, babl_format ("Y' u16"), img.data,
+ Â Â Â Â Â Â Â Â Â Â Â Â GEGL_AUTO_ROWSTRIDE);
   }
+ Â else
+ Â Â g_warning ("%s: Programmer stupidity error", G_STRLOC);
Â
  g_free (img.data);
Â
@@ -351,6 +379,7 @@ gegl_chant_class_init (GeglChantClass *klass)
   NULL);
Â
  gegl_extension_handler_register (".ppm", "gegl:ppm-load");
+ Â gegl_extension_handler_register (".pgm", "gegl:ppm-load");
 }
Â
 #endif