about summary refs log tree commit diff
path: root/analyzer/pgmhist.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-08-15 02:20:57 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-08-15 02:20:57 +0000
commitfb6b27309ee2d2e41ae8959da5ca08a9076bdf87 (patch)
tree7f29cb903abf2612d33ddfe99c5a07f79b7a5ac8 /analyzer/pgmhist.c
parentaab944c5a9333f7861d5f7fd4f62012d152ac75d (diff)
downloadnetpbm-mirror-fb6b27309ee2d2e41ae8959da5ca08a9076bdf87.tar.gz
netpbm-mirror-fb6b27309ee2d2e41ae8959da5ca08a9076bdf87.tar.xz
netpbm-mirror-fb6b27309ee2d2e41ae8959da5ca08a9076bdf87.zip
Fix arithmetic overflow
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@709 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'analyzer/pgmhist.c')
-rw-r--r--analyzer/pgmhist.c229
1 files changed, 168 insertions, 61 deletions
diff --git a/analyzer/pgmhist.c b/analyzer/pgmhist.c
index 8f4e512e..0414a3a0 100644
--- a/analyzer/pgmhist.c
+++ b/analyzer/pgmhist.c
@@ -1,4 +1,4 @@
-/* pgmhist.c - print a histogram of the values in a portable graymap
+/* pgmhist.c - print a histogram of the values in a PGM image
 **
 ** Copyright (C) 1989 by Jef Poskanzer.
 **
@@ -10,78 +10,185 @@
 ** implied warranty.
 */
 
-#include "pgm.h"
+#include <assert.h>
+
 #include "mallocvar.h"
+#include "shhopt.h"
+#include "pgm.h"
 
-int
-main( argc, argv )
-    int argc;
-    char *argv[];
-{
-    FILE *ifp;
-    gray maxval, *grayrow;
-    register gray *gP;
-    int argn, rows, cols, format, row;
-    int i, *hist, *rcount, count, size;
-    register int col;
-    const char * const usage = "[pgmfile]";
-
-    pgm_init( &argc, argv );
-
-    argn = 1;
-
-    if ( argn < argc )
-	{
-        ifp = pm_openr( argv[argn] );
-        argn++;
-	}
+
+
+struct cmdline_info {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileName;  /* Filename of input files */
+};
+
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct cmdline_info * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to us as the argv array.
+-----------------------------------------------------------------------------*/
+    optStruct3 opt;  /* set by OPTENT3 */
+    optEntry * option_def;
+    unsigned int option_def_index;
+    
+    MALLOCARRAY(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENTRY */
+
+    opt.opt_table = option_def;
+    opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
+    opt.allowNegNum = FALSE;  /* We have no parms that are negative numbers */
+
+    optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others. */
+
+    if (argc-1 == 0) 
+        cmdlineP->inputFileName = "-";
+    else if (argc-1 != 1)
+        pm_error("Program takes zero or one argument (filename).  You "
+                 "specified %d", argc-1);
     else
-        ifp = stdin;
+        cmdlineP->inputFileName = argv[1];
+}
+
 
-    if ( argn != argc )
-        pm_usage( usage );
 
-    pgm_readpgminit( ifp, &cols, &rows, &maxval, &format );
-    grayrow = pgm_allocrow( cols );
+static void
+buildHistogram(FILE *          const ifP,
+               unsigned int ** const histP,
+               gray *          const maxvalP) {
+
+    gray * grayrow;
+    int rows, cols;
+    int format;
+    unsigned int row;
+    unsigned int i;
+    unsigned int * hist;  /* malloc'ed array */
+    gray maxval;
+
+    pgm_readpgminit(ifP, &cols, &rows, &maxval, &format);
+
+    if (UINT_MAX / cols < rows)
+        pm_error("Too many pixels (%u x %u) in image.  "
+                 "Maximum computable is %u",
+                 cols, rows, UINT_MAX);
+
+    grayrow = pgm_allocrow(cols);
 
-    /* Build histogram. */
     MALLOCARRAY(hist, maxval + 1);
-    MALLOCARRAY(rcount, maxval + 1);
-    if ( hist == NULL || rcount == NULL )
-        pm_error( "out of memory" );
-    for ( i = 0; i <= maxval; i++ )
+    if (hist == NULL)
+        pm_error("out of memory");
+
+    for (i = 0; i <= maxval; ++i)
         hist[i] = 0;
-    for ( row = 0; row < rows; row++ )
-	{
-        pgm_readpgmrow( ifp, grayrow, cols, maxval, format );
-        for ( col = 0, gP = grayrow; col < cols; col++, gP++ )
-            hist[(int) *gP]++;
-	}
 
-    pm_close( ifp );
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
+
+        pgm_readpgmrow(ifP, grayrow, cols, maxval, format);
+
+        for (col = 0; col < cols; ++col) {
+            /* Because total pixels in image is limited: */
+            assert (hist[grayrow[col]] < INT_MAX);
+
+            ++hist[grayrow[col]];
+        }
+    }
+    pgm_freerow(grayrow);
+
+    *histP   = hist;
+    *maxvalP = maxval;
+}
+
+
+
+static void
+countCumulative(unsigned int    const hist[],
+                gray            const maxval,
+                unsigned int ** const rcountP) {
+
+    unsigned int * rcount;
+    unsigned int cumCount;
+    int i;
+    
+    MALLOCARRAY(rcount, maxval + 1);
+    if (rcount == NULL)
+        pm_error("out of memory");
+
+    for (i = maxval, cumCount = 0; i >= 0; --i) {
+        /* Because total pixels in image is limited: */
+        assert(UINT_MAX - hist[i] >= cumCount);
+
+        cumCount += hist[i];
+        rcount[i] = cumCount;
+    }
+
+    *rcountP = rcount;
+}
+
+
+
+static void
+report(unsigned int const hist[],
+       unsigned int const rcount[],
+       gray         const maxval) {
+
+    unsigned int const totalPixels = rcount[0];
+    unsigned int count;
+    unsigned int i;
+
+    printf("value  count  b%%      w%%   \n");
+    printf("-----  -----  ------  ------\n");
 
-    /* Compute count-down */
-    count = 0;
-    for ( i = maxval; i >= 0; i-- )
-	{
-        count += hist[i];
-        rcount[i] = count;
-	}
-
-    /* And print it. */
-    printf( "value\tcount\tb%%\tw%%\n" );
-    printf( "-----\t-----\t--\t--\n" );
     count = 0;
-    size = rows * cols;
-    for ( i = 0; i <= maxval; i++ )
-        if ( hist[i] > 0 )
-	    {
+
+    for (i = 0; i <= maxval; ++i) {
+        if (hist[i] > 0) {
             count += hist[i];
             printf(
-                "%d\t%d\t%5.3g%%\t%5.3g%%\n", i, hist[i],
-                (float) count * 100.0 / size, 
-                (float) rcount[i] * 100.0 / size );
-	    }
+                "%5d  %5d  %5.3g%%  %5.3g%%\n", i, hist[i],
+                (float) count * 100.0 / totalPixels, 
+                (float) rcount[i] * 100.0 / totalPixels);
+        }
+    }
+}
+
 
-    exit( 0 );
+
+int
+main(int argc, const char ** argv) {
+
+    struct cmdline_info cmdline;
+    FILE * ifP;
+    gray maxval;
+    unsigned int * rcount; /* malloc'ed array */
+    unsigned int * hist;   /* malloc'ed array */
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    buildHistogram(ifP, &hist, &maxval);
+
+    countCumulative(hist, maxval, &rcount);
+
+    report(hist, rcount, maxval);
+
+    free(rcount);
+    free(hist);
+    pm_close(ifP);
+
+    return 0;
 }
+
+
+