reimplement PNM reading (partial)
authorLaurent MAZET <laurent.mazet@thalesgroup.com>
Fri, 13 Sep 2024 16:38:44 +0000 (18:38 +0200)
committerLaurent MAZET <laurent.mazet@thalesgroup.com>
Fri, 13 Sep 2024 16:38:44 +0000 (18:38 +0200)
image.c
image.h
pnm.c [new file with mode: 0644]

diff --git a/image.c b/image.c
index 98ff1bb486b7e671da4a849423333ce0a120fa51..6cf8a2956fb93e381ca61d3cb64e58dc649fb1ad 100644 (file)
--- a/image.c
+++ b/image.c
@@ -2,7 +2,7 @@
 
 #include "image.h"
 
-image_t *newimage (int width, int height)
+image_t *newimage (int width, int height, int maxvalue)
 {
     image_t *image = (image_t *) calloc (1, sizeof (image_t));
     image->red = (float *) calloc (width * height, sizeof (float));
@@ -10,6 +10,7 @@ image_t *newimage (int width, int height)
     image->blue = (float *) calloc (width * height, sizeof (float));
     image->width = width;
     image->height = height;
+    image->maxvalue = maxvalue;
     return image;
 }
 
diff --git a/image.h b/image.h
index 3d8eb26f78b81ea03e41dc1d7dbd0fe6c67cb9b2..c6d7f07ef31aa207815b05eeb6a9b5ad68aca5b1 100644 (file)
--- a/image.h
+++ b/image.h
@@ -9,9 +9,10 @@ typedef struct {
     float *blue;
     int width;
     int height;
+    int maxvalue;
 } image_t;
 
-image_t *newimage (int width, int height);
+image_t *newimage (int width, int height, int maxvalue);
 
 void freeimage (image_t *image);
 
diff --git a/pnm.c b/pnm.c
new file mode 100644 (file)
index 0000000..06f0535
--- /dev/null
+++ b/pnm.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "image.h"
+
+int testpnm (FILE *fd)
+{
+    int mode = 0;
+    /* check magic number */
+    char magic[3] = {0};
+    fread (magic, 3, 1, fd);
+    if ((contain ("P", magic[0])) && (contain (" \t\n\r", magic[2]))) {
+        if ((magic[1] >= '1') && (magic[1] <= '6')) {
+            mode = '0' - magic[2];
+        }
+    }
+    return mode;
+}
+
+int getvalue (FILE *fd, int nbbytes)
+{
+    int v = fgetc (fd);
+    if (v != EOF) {
+        if (nbbytes == 2) {
+           int v0 = fgetc (fd);
+           v = (v0 != EOF) ? v * 256 + v0 : EOF;
+        }
+    }
+    return v;
+}
+
+int readpgm (FILE *fd, image_t *image)
+{
+    while (i < image->width * image->height) {
+        image->red[i] = image->green[i] = image->blue[i] = getvalue (fd, image->maxvalue);
+    }
+    return image->blue[image->width * image->height - 1];
+}
+
+int readppm (FILE *fd, image_t *image)
+{
+    while (i < image->width * image->height) {
+        image->red[i] = getvalue (fd, image->maxvalue);
+        image->green[i] = getvalue (fd, image->maxvalue);
+        image->blue[i] = getvalue (fd, image->maxvalue);
+    }
+    return image->blue[image->width * image->height - 1];
+}
+
+image_t *readpnm (char *filename)
+{
+    image_t *image = NULL;
+
+    /* open file */
+    FILE *fd = fopen (filename, "rb");
+    if (!fd) {
+        goto err;
+    }
+
+    /* test PNM type */
+    int mode = testpnm (fd);
+    if (mode == 0) {
+        goto err;
+    }
+
+    /* read parameters */
+    int width = 0;
+    int height = 0;
+    int maxvalue = 0;
+    if (!getparam (fd, &width, &height, &maxvalue)) {
+        goto err;
+    }
+
+    /* allocate image */
+    image_t *image = newimage (width, height);
+
+    /* read data */
+    int rc = 0;
+    switch (mode) {
+    case 1: // PBM ascii
+    case 2: // PGM ascii
+    case 3: // PPM ascii
+    case 4: // PBM raw
+        break;
+    case 5: // PGM raw
+        rc = readpgm (fd, image);
+        break;
+    case 6: // PPM raw
+        rc = readppm (fd, image);
+        break;
+    }
+    if (rc == 0) {
+        freeimage (image);
+        image = NULL;
+    }
+
+err:
+    if (fd) {
+        fclose (fd);
+    }
+
+    return image;
+}
+
+/* vim: set ts=4 sw=4 et: */