diff options
-rw-r--r-- | analyzer/pgmhist.c | 229 |
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; } + + + |