about summary refs log tree commit diff
path: root/lib/libpgm1.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpgm1.c')
-rw-r--r--lib/libpgm1.c221
1 files changed, 131 insertions, 90 deletions
diff --git a/lib/libpgm1.c b/lib/libpgm1.c
index 75fa365b..4d93e4be 100644
--- a/lib/libpgm1.c
+++ b/lib/libpgm1.c
@@ -10,7 +10,7 @@
 ** implied warranty.
 */
 
-/* See libpbm.c for the complicated explanation of this 32/64 bit file
+/* See pmfileio.c for the complicated explanation of this 32/64 bit file
    offset stuff.
 */
 #define _FILE_OFFSET_BITS 64
@@ -28,6 +28,7 @@
 #include "libpam.h"
 #include "fileio.h"
 #include "mallocvar.h"
+#include "nstring.h"
 
 
 gray *
@@ -49,13 +50,14 @@ void
 pgm_init(int *   const argcP,
          char ** const argv) {
 
-    pbm_init( argcP, argv );
+    pbm_init(argcP, argv);
 }
 
 
 
 void
-pgm_nextimage(FILE * const file, int * const eofP) {
+pgm_nextimage(FILE * const file,
+              int *  const eofP) {
     pm_nextimage(file, eofP);
 }
 
@@ -121,11 +123,6 @@ pgm_readpgminit(FILE * const fileP,
     /* Check magic number. */
     realFormat = pm_readmagicnumber(fileP);
     switch (PAM_FORMAT_TYPE(realFormat)) {
-    case PGM_TYPE:
-        *formatP = realFormat;
-        pgm_readpgminitrest(fileP, colsP, rowsP, maxvalP);
-        break;
-        
     case PBM_TYPE:
         *formatP = realFormat;
         pbm_readpbminitrest(fileP, colsP, rowsP);
@@ -149,6 +146,15 @@ pgm_readpgminit(FILE * const fileP,
         *maxvalP = PGM_MAXMAXVAL;
         break;
 
+    case PGM_TYPE:
+        *formatP = realFormat;
+        pgm_readpgminitrest(fileP, colsP, rowsP, maxvalP);
+        break;
+        
+    case PPM_TYPE:
+        pm_error("Input file is a PPM, which this program cannot process.  "
+                 "You may want to convert it to PGM with 'ppmtopgm'");
+
     case PAM_TYPE:
         pnm_readpaminitrestaspnm(fileP, colsP, rowsP, maxvalP, formatP);
 
@@ -158,40 +164,106 @@ pgm_readpgminit(FILE * const fileP,
         break;
 
     default:
-        pm_error("bad magic number - not a pgm or pbm file");
+        pm_error("bad magic number - not a Netpbm file");
     }
     validateComputableSize(*colsP, *rowsP);
 }
 
 
 
-gray
-pgm_getrawsample(FILE * const file,
-                 gray   const maxval) {
+static void
+readRpgmRow(FILE * const fileP,
+               gray * const grayrow, 
+               int    const cols,
+               gray   const maxval,
+               int    const format) {
+
+    unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
+    int          const bytesPerRow    = cols * bytesPerSample;
+    
+    unsigned char * rowBuffer;
+    const char * error;
+    
+    MALLOCARRAY(rowBuffer, bytesPerRow);
+    if (rowBuffer == NULL)
+        asprintfN(&error, "Unable to allocate memory for row buffer "
+                  "for %u columns", cols);
+    else {
+        ssize_t rc;
+        rc = fread(rowBuffer, 1, bytesPerRow, fileP);
+        if (rc == 0)
+            asprintfN(&error, "Error reading row.  fread() errno=%d (%s)",
+                      errno, strerror(errno));
+        else if (rc != bytesPerRow)
+            asprintfN(&error, "Error reading row.  Short read of %u bytes "
+                      "instead of %u", rc, bytesPerRow);
+        else {
+            error = NULL;
+            if (maxval < 256) {
+                unsigned int col;
+                for (col = 0; col < cols; ++col)
+                    grayrow[col] = (gray)rowBuffer[col];
+            } else {
+                unsigned int bufferCursor;
+                unsigned int col;
+                
+                bufferCursor = 0;  /* Start at beginning of rowBuffer[] */
+                
+                for (col = 0; col < cols; ++col) {
+                    gray g;
+                    
+                    g = rowBuffer[bufferCursor++] << 8;
+                    g |= rowBuffer[bufferCursor++];
+                    
+                    grayrow[col] = g;
+                }
+            }
+        }
+        free(rowBuffer);
+    }
+    if (error) {
+        pm_errormsg("%s", error);
+        strfree(error);
+        pm_longjmp();
+    }
+} 
+
+
 
-    if (maxval < 256) {
-        /* The sample is just one byte.  Read it. */
-        return(pm_getrawbyte(file));
+static void
+readPbmRow(FILE * const fileP,
+           gray * const grayrow, 
+           int    const cols,
+           gray   const maxval,
+           int    const format) {
+
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
+    bit * bitrow;
+    
+    bitrow = pbm_allocrow(cols);
+    if (setjmp(jmpbuf) != 0) {
+        pbm_freerow(bitrow);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
     } else {
-        /* The sample is two bytes.  Read both. */
-        unsigned char byte_pair[2];
-        size_t pairs_read;
-
-        pairs_read = fread(&byte_pair, 2, 1, file);
-        if (pairs_read == 0) 
-            pm_error("EOF /read error while reading a long sample");
-        /* This could be a few instructions faster if exploited the internal
-           format (i.e. endianness) of a pixval.  Then we might be able to
-           skip the shifting and oring.
-           */
-        return((byte_pair[0]<<8) | byte_pair[1]);
+        unsigned int col;
+
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
+
+        pbm_readpbmrow(fileP, bitrow, cols, format);
+        for (col = 0; col < cols; ++col)
+            grayrow[col] = (bitrow[col] == PBM_WHITE ) ? maxval : 0;
+
+        pm_setjmpbuf(origJmpbufP);
     }
+    pbm_freerow(bitrow);
 }
 
 
 
 void
-pgm_readpgmrow(FILE * const file,
+pgm_readpgmrow(FILE * const fileP,
                gray * const grayrow, 
                int    const cols,
                gray   const maxval,
@@ -201,7 +273,7 @@ pgm_readpgmrow(FILE * const file,
     case PGM_FORMAT: {
         unsigned int col;
         for (col = 0; col < cols; ++col) {
-            grayrow[col] = pm_getuint(file);
+            grayrow[col] = pm_getuint(fileP);
             if (grayrow[col] > maxval)
                 pm_error("value out of bounds (%u > %u)",
                          grayrow[col], maxval);
@@ -209,86 +281,56 @@ pgm_readpgmrow(FILE * const file,
     }
     break;
         
-    case RPGM_FORMAT: {
-        unsigned int const bytesPerSample = maxval < 256 ? 1 : 2;
-        int          const bytesPerRow    = cols * bytesPerSample;
-
-        unsigned char * rowBuffer;
-        ssize_t rc;
-
-        MALLOCARRAY(rowBuffer, bytesPerRow);
-        if (rowBuffer == NULL)
-            pm_error("Unable to allocate memory for row buffer "
-                     "for %u columns", cols);
-
-        rc = fread(rowBuffer, 1, bytesPerRow, file);
-        if (rc == 0)
-            pm_error("Error reading row.  fread() errno=%d (%s)",
-                     errno, strerror(errno));
-        else if (rc != bytesPerRow)
-            pm_error("Error reading row.  Short read of %u bytes "
-                     "instead of %u", rc, bytesPerRow);
-
-        if (maxval < 256) {
-            unsigned int col;
-            for (col = 0; col < cols; ++col)
-                grayrow[col] = (gray)rowBuffer[col];
-        } else {
-            unsigned int bufferCursor;
-            unsigned int col;
-
-            bufferCursor = 0;  /* Start at beginning of rowBuffer[] */
-
-            for (col = 0; col < cols; ++col) {
-                gray g;
-
-                g = rowBuffer[bufferCursor++] << 8;
-                g |= rowBuffer[bufferCursor++];
-
-                grayrow[col] = g;
-            }
-        }
-        free(rowBuffer);
-    }
+    case RPGM_FORMAT:
+        readRpgmRow(fileP, grayrow, cols, maxval, format);
         break;
     
     case PBM_FORMAT:
-    case RPBM_FORMAT: {
-        bit * bitrow;
-        int col;
-
-        bitrow = pbm_allocrow(cols);
-        pbm_readpbmrow( file, bitrow, cols, format );
-        for (col = 0; col < cols; ++col)
-            grayrow[col] = (bitrow[col] == PBM_WHITE ) ? maxval : 0;
-        pbm_freerow(bitrow);
-    }
+    case RPBM_FORMAT:
+        readPbmRow(fileP, grayrow, cols, maxval, format);
         break;
         
     default:
-        pm_error( "can't happen" );
+        pm_error("can't happen");
     }
 }
 
 
 
 gray **
-pgm_readpgm(FILE * const file,
+pgm_readpgm(FILE * const fileP,
             int *  const colsP,
             int *  const rowsP, 
             gray * const maxvalP) {
 
-    gray** grays;
-    int row;
+    gray ** grays;
+    int rows, cols;
+    gray maxval;
     int format;
+    jmp_buf jmpbuf;
+    jmp_buf * origJmpbufP;
 
-    pgm_readpgminit( file, colsP, rowsP, maxvalP, &format );
+    pgm_readpgminit(fileP, &cols, &rows, &maxval, &format);
     
-    grays = pgm_allocarray( *colsP, *rowsP );
-    
-    for ( row = 0; row < *rowsP; ++row )
-        pgm_readpgmrow( file, grays[row], *colsP, *maxvalP, format );
+    grays = pgm_allocarray(cols, rows);
+
+    if (setjmp(jmpbuf) != 0) {
+        pgm_freearray(grays, rows);
+        pm_setjmpbuf(origJmpbufP);
+        pm_longjmp();
+    } else {
+        unsigned int row;
     
+        pm_setjmpbufsave(&jmpbuf, &origJmpbufP);
+
+        for (row = 0; row < rows; ++row)
+            pgm_readpgmrow(fileP, grays[row], cols, maxval, format);
+
+        pm_setjmpbuf(origJmpbufP);
+    }
+    *colsP = cols;
+    *rowsP = rows;
+    *maxvalP = maxval;
     return grays;
 }
 
@@ -319,6 +361,5 @@ pgm_check(FILE *               const file,
         pm_filepos const need_raster_size = rows * bytes_per_row;
         
         pm_check(file, check_type, need_raster_size, retval_p);
-        
     }
 }