reimplement PNM reading (raw)
authorLaurent Mazet <mazet@softndesign.org>
Fri, 13 Sep 2024 23:11:35 +0000 (01:11 +0200)
committerLaurent Mazet <mazet@softndesign.org>
Fri, 13 Sep 2024 23:11:35 +0000 (01:11 +0200)
display.c
image.c
image.h
pgm.c [deleted file]
pgm.h [deleted file]
pnm.c
pnm.h [new file with mode: 0644]
ppm.c [deleted file]
ppm.h [deleted file]

index b2aa9e7f4134745c0ece70943105d78af2c4da4b..2ed3d9a0bbdda5f65ba28a6a7ffc598bb6b98070 100644 (file)
--- a/display.c
+++ b/display.c
@@ -1,8 +1,8 @@
 /* depend: */
 /* cflags: */
-/* linker: color.o debug.o image.o pgm.o ppm.o -lm */
-/* doslnk: color.o debug.o image.o pgm.o ppm.o -lm */
-/* winlnk: color.o debug.o image.o pgm.o ppm.o -lm */
+/* linker: color.o debug.o image.o pnm.o -lm */
+/* doslnk: color.o debug.o image.o pnm.o -lm */
+/* winlnk: color.o debug.o image.o pnm.o -lm */
 
 #include <math.h>
 #include <stdio.h>
 #include "color.h"
 #include "debug.h"
 #include "image.h"
-#include "pgm.h"
-#include "ppm.h"
+#include "pnm.h"
 
 /* static variables */
 char *progname = NULL;
 char *version = "0.1";
 
-float gf[3] = { 1.0, 1.0, 1.0 };
+float gf[3] = { 1.0f, 1.0f, 1.0f };
 int mode = 0;
 
 /* help message */
 int usage (int ret)
 {
     FILE *fd = ret ? stderr : stdout;
-    fprintf (fd, "usage: %s [-g gamma] [-h] [-t|-w] <file>\n", progname);
+    fprintf (fd, "usage: %s [-g gamma] [-h] [-t|-w] [-v int] <file>\n", progname);
     fprintf (fd, " -g: gamma correction (%.1f:%.1f:%.1f)\n", gf[0], gf[1], gf[2]);
     fprintf (fd, " -h: help message\n");
     fprintf (fd, " -t: thin mode (%s)\n", (mode == 0) ? "on" : "off");
+    fprintf (fd, " -v: verbose level (%d)\n", verbose);
     fprintf (fd, " -w: wide mode (%s)\n", (mode == 1) ? "on" : "off");
     fprintf (fd, "%s version %s\n", progname, version);
 
@@ -87,6 +87,14 @@ int main (int argc, char *argv[])
         case 't':
             mode = 0;
             break;
+        case 'v':
+            arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+            if (arg == NULL) {
+                VERBOSE (ERROR, fprintf (stderr, "%s: missing verbose level\n", progname));
+                return usage (1);
+            }
+            verbose = atoi (arg);
+            break;
         case 'w':
             mode = 1;
             break;
@@ -107,7 +115,7 @@ int main (int argc, char *argv[])
     }
 
     /* main process */
-    image_t *image = readppm (filename);
+    image_t *image = readpnm (filename);
 
     int k, l;
     for (l = 0; l < image->height; l++) {
@@ -126,5 +134,6 @@ int main (int argc, char *argv[])
 /* test: display.exe -g 2>&1 | grep 'no gamma specified' */
 /* test: display.exe -g -1.0 2>&1 | grep 'incorrect gamma' */
 /* test: display.exe -h | grep usage */
+/* test: display.exe -v 2>&1 | grep missing */
 
 /* vim: set ts=4 sw=4 et: */
diff --git a/image.c b/image.c
index 6cf8a2956fb93e381ca61d3cb64e58dc649fb1ad..49cb9fb36e3687aee153bd33d78343d79f46309f 100644 (file)
--- a/image.c
+++ b/image.c
@@ -33,26 +33,4 @@ int contain (char *str, char c)
     return 1;
 }
 
-int readnumber (FILE *fd)
-{
-    int num = 0;
-    fscanf (fd, "%d", &num);
-    char c = 0;
-    c = fgetc (fd);
-    if (!contain (" \t\n\r", c)) {
-        num = 0;
-    }
-    return num;
-}
-
-float getvalue (unsigned char *buffer, int maxvalue)
-{
-    float value = *(buffer++) / (float)maxvalue;
-    if (maxvalue > 255) {
-        value *= 256;
-        value += *buffer / (float)maxvalue;
-    }
-    return value;
-}
-
 /* vim: set ts=4 sw=4 et: */
diff --git a/image.h b/image.h
index c6d7f07ef31aa207815b05eeb6a9b5ad68aca5b1..e6542aa9d15468ba692b68eba83eab55dfdad917 100644 (file)
--- a/image.h
+++ b/image.h
@@ -18,8 +18,4 @@ void freeimage (image_t *image);
 
 int contain (char *str, char c);
 
-int readnumber (FILE *fd);
-
-float getvalue (unsigned char *buffer, int maxvalue);
-
 #endif /* __IMAGE_H__ */
diff --git a/pgm.c b/pgm.c
deleted file mode 100644 (file)
index 9dd11b0..0000000
--- a/pgm.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "image.h"
-
-image_t *readpgm (char *filename)
-{
-    unsigned char *buffer = NULL;
-    image_t *image = NULL;
-
-    /* open file */
-    FILE *fd = fopen (filename, "rb");
-    if (!fd) {
-        return NULL;
-    }
-
-    /* check magic number */
-    char magic[3] = {0};
-    fread (magic, 3, 1, fd);
-    if ((!contain ("P", magic[0])) ||
-        (!contain ("5", magic[1])) ||
-        (!contain (" \t\n\r", magic[2]))) {
-        goto err;
-    }
-
-    /* get width */
-    int width = readnumber (fd);
-    if (width == 0) {
-        goto err;
-    }
-
-    /* get height */
-    int height = readnumber (fd);
-    if (height == 0) {
-        goto err;
-    }
-
-    /* get maxvalue */
-    int maxvalue = readnumber (fd);
-    if (maxvalue == 0) {
-        goto err;
-    }
-
-    /* read full image */
-    int size = width * height * ((maxvalue > 255) ? 2 : 1);
-    buffer = (unsigned char *) calloc (size, 1);
-    if (!fread (buffer, size, 1, fd)) {
-        goto err;
-    }
-
-    /* create image */
-    image = newimage (width, height);
-    int i = 0;
-    int gap = (maxvalue > 255) ? 2 : 1;
-    while (i < width * height) {
-        image->red[i] = image->green[i] = image->blue[i] = getvalue (buffer + gap * i, maxvalue);
-        i++;
-    }
-
-err:
-    free (buffer);
-    fclose (fd);
-    return image;
-}
-
-/* vim: set ts=4 sw=4 et: */
diff --git a/pgm.h b/pgm.h
deleted file mode 100644 (file)
index b634a8f..0000000
--- a/pgm.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __PGM_H__
-#define __PGM_H__
-
-#include "image.h"
-
-image_t *readpgm (char *filename);
-
-#endif /* __PPM_H__ */
diff --git a/pnm.c b/pnm.c
index 06f0535f1556f2e67b3e3e3727b3dc37de461305..6c90bf401bab75b838bcc81fa0db853e94274d50 100644 (file)
--- a/pnm.c
+++ b/pnm.c
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include "debug.h"
 #include "image.h"
 
 int testpnm (FILE *fd)
@@ -11,40 +12,96 @@ int testpnm (FILE *fd)
     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];
+            mode = magic[1] - '0';
         }
     }
     return mode;
 }
 
+int getparam (FILE *fd, int *value)
+{
+    int start = 0;
+    *value = 0;
+    while (!feof (fd)) {
+        int c = fgetc (fd);
+        if (contain ("#", c)) {
+            while (!feof (fd)) {
+                c = fgetc (fd);
+                if (contain ("\n\r", c)) {
+                    break;
+                }
+            }
+        }
+        if (contain ("0123456789", c)) {
+            *value = 10 * *value + c - '0';
+            start = 1;
+        }
+        if ((start) && (contain (" \n\r\t", c))) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
 int getvalue (FILE *fd, int nbbytes)
 {
-    int v = fgetc (fd);
-    if (v != EOF) {
+    int value = fgetc (fd);
+    if (value != EOF) {
         if (nbbytes == 2) {
-           int v0 = fgetc (fd);
-           v = (v0 != EOF) ? v * 256 + v0 : EOF;
+            int value0 = fgetc (fd);
+            value = (value0 != EOF) ? value * 256 + value0 : EOF;
+        }
+    }
+    return value;
+}
+
+int readpbm (FILE *fd, image_t *image)
+{
+    int i = 0;
+    int k = 0;
+    int value = EOF;
+    while (i < image->width * image->height) {
+        if (k == 0) {
+            value = fgetc (fd);
+            k = 8;
+        }
+        image->red[i] = image->green[i] = image->blue[i] = !((value >> --k) & 1);
+        i++;
+        if (i % image->width == 0) {
+            k = 0;
         }
     }
-    return v;
+    return (value != EOF);
 }
 
 int readpgm (FILE *fd, image_t *image)
 {
+    int i = 0;
+    int nbbytes = (image->maxvalue > 255) ? 2 : 1;
+    int value = EOF;
     while (i < image->width * image->height) {
-        image->red[i] = image->green[i] = image->blue[i] = getvalue (fd, image->maxvalue);
+        value = getvalue (fd, nbbytes);
+        image->red[i] = image->green[i] = image->blue[i] = value / (float)image->maxvalue;
+        i++;
     }
-    return image->blue[image->width * image->height - 1];
+    return (value != EOF);
 }
 
 int readppm (FILE *fd, image_t *image)
 {
+    int i = 0;
+    int nbbytes = (image->maxvalue > 255) ? 2 : 1;
+    int value = EOF;
     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);
+        value = getvalue (fd, nbbytes);
+        image->red[i] = value / (float)image->maxvalue;
+        value = getvalue (fd, nbbytes);
+        image->green[i] = value / (float)image->maxvalue;
+        value = getvalue (fd, nbbytes);
+        image->blue[i] = value / (float)image->maxvalue;
+        i++;
     }
-    return image->blue[image->width * image->height - 1];
+    return (value != EOF);
 }
 
 image_t *readpnm (char *filename)
@@ -62,17 +119,29 @@ image_t *readpnm (char *filename)
     if (mode == 0) {
         goto err;
     }
+    VERBOSE (DEBUG, printf ("mode: %d\n", mode));
 
     /* read parameters */
     int width = 0;
+    if (!getparam (fd, &width)) {
+        goto err;
+    }
+    VERBOSE (DEBUG, printf ("width: %d\n", width));
     int height = 0;
-    int maxvalue = 0;
-    if (!getparam (fd, &width, &height, &maxvalue)) {
+    if (!getparam (fd, &height)) {
         goto err;
     }
+    VERBOSE (DEBUG, printf ("height: %d\n", height));
+    int maxvalue = 1;
+    if ((mode != 1) && (mode != 4)) {
+        if (!getparam (fd, &maxvalue)) {
+            goto err;
+        }
+    }
+    VERBOSE (DEBUG, printf ("maxvalue: %d\n", maxvalue));
 
     /* allocate image */
-    image_t *image = newimage (width, height);
+    image = newimage (width, height, maxvalue);
 
     /* read data */
     int rc = 0;
@@ -81,6 +150,7 @@ image_t *readpnm (char *filename)
     case 2: // PGM ascii
     case 3: // PPM ascii
     case 4: // PBM raw
+        rc = readpbm (fd, image);
         break;
     case 5: // PGM raw
         rc = readpgm (fd, image);
diff --git a/pnm.h b/pnm.h
new file mode 100644 (file)
index 0000000..04fbfd8
--- /dev/null
+++ b/pnm.h
@@ -0,0 +1,8 @@
+#ifndef __PNM_H__
+#define __PNM_H__
+
+#include "image.h"
+
+image_t *readpnm (char *filename);
+
+#endif /* __PNM_H__ */
diff --git a/ppm.c b/ppm.c
deleted file mode 100644 (file)
index b5efcd3..0000000
--- a/ppm.c
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "image.h"
-
-image_t *readppm (char *filename)
-{
-    unsigned char *buffer = NULL;
-    image_t *image = NULL;
-
-    /* open file */
-    FILE *fd = fopen (filename, "rb");
-    if (!fd) {
-        return NULL;
-    }
-
-    /* check magic number */
-    char magic[3] = {0};
-    fread (magic, 3, 1, fd);
-    if ((!contain ("P", magic[0])) ||
-        (!contain ("6", magic[1])) ||
-        (!contain (" \t\n\r", magic[2]))) {
-        goto err;
-    }
-
-    /* get width */
-    int width = readnumber (fd);
-    if (width == 0) {
-        goto err;
-    }
-
-    /* get height */
-    int height = readnumber (fd);
-    if (height == 0) {
-        goto err;
-    }
-
-    /* get maxcolor */
-    int maxcolor = readnumber (fd);
-    if (maxcolor == 0) {
-        goto err;
-    }
-
-    /* read full image */
-    int size = 3 * width * height * ((maxcolor > 255) ? 2 : 1);
-    buffer = (unsigned char *) calloc (size, 1);
-    if (!fread (buffer, size, 1, fd)) {
-        goto err;
-    }
-
-    /* create image */
-    image = newimage (width, height);
-    int i = 0;
-    int gap = (maxcolor > 255) ? 2 : 1;
-    while (i < width * height) {
-        image->red[i] = getvalue (buffer + (3 * gap) * i, maxcolor);
-        image->green[i] = getvalue (buffer + (3 * gap) * i + gap, maxcolor);
-        image->blue[i] = getvalue (buffer + (3 * gap) * i + 2 * gap, maxcolor);
-        i++;
-    }
-
-err:
-    free (buffer);
-    fclose (fd);
-    return image;
-}
-
-/* vim: set ts=4 sw=4 et: */
diff --git a/ppm.h b/ppm.h
deleted file mode 100644 (file)
index 2a29bdd..0000000
--- a/ppm.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __PPM_H__
-#define __PPM_H__
-
-#include "image.h"
-
-image_t *readppm (char *filename);
-
-#endif /* __PPM_H__ */