about summary refs log tree commit diff
path: root/analyzer/pnmhistmap.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2016-03-27 01:46:26 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2016-03-27 01:46:26 +0000
commitdff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa (patch)
treeb147568ccffc4cdba9e2a98de1452450ba8e55c3 /analyzer/pnmhistmap.c
parent4ce684c4978610d1ea42be1b00f7332f3f5f337a (diff)
downloadnetpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.tar.gz
netpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.tar.xz
netpbm-mirror-dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa.zip
Promote Advanced (10.73) to Stable
git-svn-id: http://svn.code.sf.net/p/netpbm/code/stable@2692 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'analyzer/pnmhistmap.c')
-rw-r--r--analyzer/pnmhistmap.c342
1 files changed, 197 insertions, 145 deletions
diff --git a/analyzer/pnmhistmap.c b/analyzer/pnmhistmap.c
index 7e504734..fc1bbbde 100644
--- a/analyzer/pnmhistmap.c
+++ b/analyzer/pnmhistmap.c
@@ -17,6 +17,7 @@
  * - Deal properly with maxvals other than 256
  */
 
+#include <assert.h>
 #include <string.h>
 
 #include "pm_c_util.h"
@@ -26,8 +27,6 @@
 
 static double const epsilon = .00001;
 
-#define SCALE_H(value) (hscale_unity ? (value) : (int)((value) * hscale))
-
 enum wantedColor {WANT_RED=0, WANT_GRN=1, WANT_BLU=2};
 
 struct cmdlineInfo {
@@ -53,14 +52,14 @@ struct cmdlineInfo {
 
 
 static void
-parseCommandLine(int argc, char ** argv,
+parseCommandLine(int argc, const char ** argv,
                  struct cmdlineInfo *cmdlineP) {
 /*----------------------------------------------------------------------------
    Note that the file spec array we return is stored in the storage that
    was passed to us as the argv array.
 -----------------------------------------------------------------------------*/
     optEntry *option_def;
-        /* Instructions to optParseOptions3 on how to parse our options.
+        /* Instructions to pm_optParseOptions3 on how to parse our options.
          */
     optStruct3 opt;
 
@@ -93,7 +92,7 @@ parseCommandLine(int argc, char ** argv,
     opt.short_allowed = FALSE;  /* We have no short (old-fashioned) options */
     opt.allowNegNum = FALSE;  /* We may have parms that are negative numbers */
 
-    optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
+    pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
     if (!lvalSpec)
@@ -118,7 +117,7 @@ parseCommandLine(int argc, char ** argv,
         cmdlineP->inputFilespec = "-";
     else if (argc-1 != 1)
         pm_error("Program takes zero or one argument (filename).  You "
-                 "specified %d", argc-1);
+                 "specified %u", argc-1);
     else
         cmdlineP->inputFilespec = argv[1];
 }
@@ -127,7 +126,7 @@ parseCommandLine(int argc, char ** argv,
 
 static unsigned int
 maxSlotCount(const unsigned int * const hist,
-             unsigned int         const hist_width,
+             unsigned int         const histWidth,
              bool                 const no_white,
              bool                 const no_black) {
 /*----------------------------------------------------------------------------
@@ -138,7 +137,7 @@ maxSlotCount(const unsigned int * const hist,
     unsigned int i;
 
     unsigned int const start = (no_black ? 1 : 0);
-    unsigned int const finish = (no_white ? hist_width - 1 : hist_width);
+    unsigned int const finish = (no_white ? histWidth - 1 : histWidth);
     for (hmax = 0, i = start; i < finish; ++i)
         if (hmax < hist[i])
             hmax = hist[i];
@@ -150,36 +149,52 @@ maxSlotCount(const unsigned int * const hist,
 
 static void
 clipHistogram(unsigned int * const hist,
-              unsigned int   const hist_width,
+              unsigned int   const histWidth,
               unsigned int   const hmax) {
 
     unsigned int i;
 
-    for (i = 0; i < hist_width; ++i)
+    for (i = 0; i < histWidth; ++i)
         hist[i] = MIN(hmax, hist[i]);
 }
 
 
 
 static void
-pgm_hist(FILE *       const ifP,
-         int          const cols,
-         int          const rows,
-         xelval       const maxval,
-         int          const format,
-         bool         const dots,
-         bool         const no_white,
-         bool         const no_black,
-         bool         const verbose,
-         xelval       const startval,
-         xelval       const endval,
-         unsigned int const hist_width,
-         unsigned int const hist_height,
-         bool         const clipSpec,
-         unsigned int const clipCount,
-         double       const hscale) {
-
-    bool const hscale_unity = hscale - 1 < epsilon;
+countComp(xelval         const value,
+          xelval         const startval,
+          xelval         const endval,
+          unsigned int   const histWidth,
+          unsigned int * const hist) {
+
+    double const hscale = (float)(histWidth-1) / (endval - startval - 1);
+
+    if (value >= startval && value < endval) {
+        unsigned int const bin = ROUNDU((value-startval) * hscale);
+
+        assert(bin < histWidth);
+        ++hist[bin];
+    }
+}
+
+
+
+static void
+pgmHist(FILE *       const ifP,
+        int          const cols,
+        int          const rows,
+        xelval       const maxval,
+        int          const format,
+        bool         const dots,
+        bool         const no_white,
+        bool         const no_black,
+        bool         const verbose,
+        xelval       const startval,
+        xelval       const endval,
+        unsigned int const histWidth,
+        unsigned int const histHeight,
+        bool         const clipSpec,
+        unsigned int const clipCount) {
 
     gray * grayrow;
     bit ** bits;
@@ -188,15 +203,15 @@ pgm_hist(FILE *       const ifP,
     double vscale;
     unsigned int hmax;
     
-    MALLOCARRAY(ghist, hist_width);
+    MALLOCARRAY(ghist, histWidth);
     if (ghist == NULL)
-        pm_error("Not enough memory for histogram array (%d bytes)",
-                  hist_width * sizeof(int));
-    bits = pbm_allocarray(hist_width, hist_height);
+        pm_error("Not enough memory for histogram array (%u bytes)",
+                 histWidth * (unsigned)sizeof(int));
+    bits = pbm_allocarray(histWidth, histHeight);
     if (bits == NULL)
-        pm_error("no space for output array (%d bits)",
-                 hist_width * hist_height);
-    memset(ghist, 0, hist_width * sizeof(ghist[0]));
+        pm_error("no space for output array (%u bits)",
+                 histWidth * histHeight);
+    memset(ghist, 0, histWidth * sizeof(ghist[0]));
 
     /* read the pixel values into the histogram arrays */
     grayrow = pgm_allocrow(cols);
@@ -206,12 +221,8 @@ pgm_hist(FILE *       const ifP,
 
     for (i = rows; i > 0; --i) {
         pgm_readpgmrow (ifP, grayrow, cols, maxval, format);
-        for (j = cols-1; j >= 0; --j) {
-            int const value = grayrow[j];
-
-            if (value >= startval && value <= endval)
-                ++ghist[SCALE_H(value-startval)];
-        }
+        for (j = cols-1; j >= 0; --j)
+            countComp(grayrow[j], startval, endval, histWidth, ghist);
     }
     pgm_freerow(grayrow);
 
@@ -221,33 +232,35 @@ pgm_hist(FILE *       const ifP,
     if (clipSpec)
         hmax = clipCount;
     else 
-        hmax = maxSlotCount(ghist, hist_width, no_white, no_black);
+        hmax = maxSlotCount(ghist, histWidth, no_white, no_black);
+
+    assert(hmax > 0);
 
     if (verbose)
         pm_message("Done: height = %u", hmax);
 
-    clipHistogram(ghist, hist_width, hmax);
+    clipHistogram(ghist, histWidth, hmax);
 
-    vscale = (double) hist_height / hmax;
+    vscale = (double) histHeight / hmax;
 
-    for (i = 0; i < hist_width; ++i) {
-        int mark = hist_height - (int)(vscale * ghist[i]);
+    for (i = 0; i < histWidth; ++i) {
+        int mark = histHeight - (int)(vscale * ghist[i]);
         for (j = 0; j < mark; ++j)
             bits[j][i] = PBM_BLACK;
-        if (j < hist_height)
+        if (j < histHeight)
             bits[j++][i] = PBM_WHITE;
-        for ( ; j < hist_height; ++j)
+        for ( ; j < histHeight; ++j)
             bits[j][i] = dots ? PBM_BLACK : PBM_WHITE;
     }
 
-    pbm_writepbm(stdout, bits, hist_width, hist_height, 0);
+    pbm_writepbm(stdout, bits, histWidth, histHeight, 0);
 }
 
 
 
 static unsigned int
 maxSlotCountAll(unsigned int *       const hist[3],
-                unsigned int         const hist_width,
+                unsigned int         const histWidth,
                 bool                 const no_white,
                 bool                 const no_black) {
 /*----------------------------------------------------------------------------
@@ -264,7 +277,7 @@ maxSlotCountAll(unsigned int *       const hist[3],
         if (hist[color])
             hmax = MAX(hmax, 
                        maxSlotCount(hist[color], 
-                                    hist_width, no_white, no_black));
+                                    histWidth, no_white, no_black));
     
     return hmax;
 }
@@ -273,107 +286,132 @@ maxSlotCountAll(unsigned int *       const hist[3],
 
 static void
 createHist(bool             const colorWanted[3],
-           unsigned int     const hist_width,
+           unsigned int     const histWidth,
            unsigned int * (* const histP)[3]) {
 /*----------------------------------------------------------------------------
    Allocate the histogram arrays and set each slot count to zero.
 -----------------------------------------------------------------------------*/
     unsigned int color;
 
-    for (color = 0; color < 3; ++color)
+    for (color = 0; color < 3; ++color) {
         if (colorWanted[color]) {
             unsigned int * hist;
             unsigned int i;
-            MALLOCARRAY(hist, hist_width);
+            MALLOCARRAY(hist, histWidth);
             if (hist == NULL)
-                pm_error ("Not enough memory for histogram arrays (%u bytes)",
-                          hist_width * sizeof(int) * 3);
+                pm_error("Not enough memory for histogram arrays (%u bytes)",
+                         histWidth * (unsigned)sizeof(hist[0]) * 3);
 
-            for (i = 0; i < hist_width; ++i)
+            for (i = 0; i < histWidth; ++i)
                 hist[i] = 0;
             (*histP)[color] = hist;
         } else
             (*histP)[color] = NULL;
+    }
 }
 
 
 
 static void
 clipHistogramAll(unsigned int * const hist[3],
-                 unsigned int   const hist_width,
+                 unsigned int   const histWidth,
                  unsigned int   const hmax) {
 
     unsigned int color;
 
     for (color = 0; color < 3; ++color)
         if (hist[color])
-            clipHistogram(hist[color], hist_width, hmax);
+            clipHistogram(hist[color], histWidth, hmax);
 }
 
 
 
 static void
-ppm_hist(FILE *       const ifP,
-         int          const cols,
-         int          const rows,
-         xelval       const maxval,
-         int          const format,
-         bool         const dots,
-         bool         const no_white,
-         bool         const no_black,
-         bool         const colorWanted[3],
-         bool         const verbose,
-         xelval       const startval,
-         xelval       const endval,
-         unsigned int const hist_width,
-         unsigned int const hist_height,
-         bool         const clipSpec,
-         unsigned int const clipCount,
-         double       const hscale) {
-
-    bool const hscale_unity = hscale - 1 < epsilon;
-
+fillPpmBins(FILE *          const ifP,
+            unsigned int    const cols,
+            unsigned int    const rows,
+            xelval          const maxval,
+            int             const format,
+            bool            const colorWanted[3],
+            bool            const verbose,
+            xelval          const startval,
+            xelval          const endval,
+            unsigned int    const histWidth,
+            unsigned int ** const hist) {
+/*----------------------------------------------------------------------------
+   For each wanted color component, given by colorWanted[], hist[color] is the
+   histogram.  Each histogram as 'histWidth' bins; we ignore color component
+   values less than 'startval' and greater than or equal to 'endval' and
+   spread the rest evenly across the 'histWidth' bins.
+
+   We get the color component values from the PNM image on *ifP,
+   which is positioned to the raster, whose format is described
+   by 'cols', 'rows', 'maxval', and 'format'.
+-----------------------------------------------------------------------------*/
     pixel * pixrow;
-    pixel ** pixels;
-    int i, j;
-    unsigned int * hist[3];  /* Subscript is enum wantedColor */
-    double vscale;
-    unsigned int hmax;
-
-    createHist(colorWanted, hist_width, &hist);
+    unsigned int row;
 
-    if ((pixels = ppm_allocarray (hist_width, hist_height)) == NULL)
-        pm_error("no space for output array (%d pixels)",
-                 hist_width * hist_height);
-    for (i = 0; i < hist_height; ++i)
-        memset(pixels[i], 0, hist_width * sizeof(pixels[i][0]));
-
-    /* read the pixel values into the histogram arrays */
     pixrow = ppm_allocrow(cols);
 
     if (verbose)
         pm_message("making histogram...");
 
-    for (i = rows; i > 0; --i) {
+    for (row = 0; row < rows; ++row) {
+        unsigned int col;
         ppm_readppmrow(ifP, pixrow, cols, maxval, format);
-        for (j = cols-1; j >= 0; --j) {
-            int value;
-
-            if (colorWanted[WANT_RED] && 
-                (value = PPM_GETR(pixrow[j])) >= startval && 
-                value <= endval)
-                hist[WANT_RED][SCALE_H(value-startval)]++;
-            if (colorWanted[WANT_GRN] && 
-                (value = PPM_GETG(pixrow[j])) >= startval && 
-                value <= endval)
-                hist[WANT_GRN][SCALE_H(value-startval)]++;
-            if (colorWanted[WANT_BLU] && 
-                (value = PPM_GETB(pixrow[j])) >= startval && 
-                value <= endval)
-                hist[WANT_BLU][SCALE_H(value-startval)]++;
+        for (col = 0; col < cols; ++col) {
+            if (colorWanted[WANT_RED])
+                countComp(PPM_GETR(pixrow[col]),
+                          startval, endval, histWidth, hist[WANT_RED]);
+
+            if (colorWanted[WANT_GRN])
+                countComp(PPM_GETG(pixrow[col]),
+                          startval, endval, histWidth, hist[WANT_GRN]);
+
+            if (colorWanted[WANT_BLU])
+                countComp(PPM_GETB(pixrow[col]),
+                          startval, endval, histWidth, hist[WANT_BLU]);
         }
     }
     ppm_freerow(pixrow);
+}
+
+
+
+static void
+ppmHist(FILE *       const ifP,
+        unsigned int const cols,
+        unsigned int const rows,
+        xelval       const maxval,
+        int          const format,
+        bool         const dots,
+        bool         const no_white,
+        bool         const no_black,
+        bool         const colorWanted[3],
+        bool         const verbose,
+        xelval       const startval,
+        xelval       const endval,
+        unsigned int const histWidth,
+        unsigned int const histHeight,
+        bool         const clipSpec,
+        unsigned int const clipCount) {
+
+    pixel ** pixels;
+    unsigned int i;
+    unsigned int * hist[3];  /* Subscript is enum wantedColor */
+    double vscale;
+    unsigned int hmax;
+
+    createHist(colorWanted, histWidth, &hist);
+
+    if ((pixels = ppm_allocarray (histWidth, histHeight)) == NULL)
+        pm_error("no space for output array (%u pixels)",
+                 histWidth * histHeight);
+    for (i = 0; i < histHeight; ++i)
+        memset(pixels[i], 0, histWidth * sizeof(pixels[i][0]));
+
+    fillPpmBins(ifP, cols, rows, maxval, format, colorWanted, verbose,
+                startval, endval, histWidth, hist);
 
     /* find the highest-valued slot and set the vertical scale value */
     if (verbose)
@@ -381,22 +419,24 @@ ppm_hist(FILE *       const ifP,
     if (clipSpec)
         hmax = clipCount;
     else 
-        hmax = maxSlotCountAll(hist, hist_width, no_white, no_black);
+        hmax = maxSlotCountAll(hist, histWidth, no_white, no_black);
 
-    clipHistogramAll(hist, hist_width, hmax);
+    assert(hmax > 0);
 
-    vscale = (double) hist_height / hmax;
-    if (verbose)
-        pm_message("Done: height = %d, vertical scale factor = %g", 
+    clipHistogramAll(hist, histWidth, hmax);
+
+    vscale = (double) histHeight / hmax;
+    if (verbose && pm_have_float_format())
+        pm_message("Done: height = %u, vertical scale factor = %g", 
                    hmax, vscale);
 
-    for (i = 0; i < hist_width; ++i) {
+    for (i = 0; i < histWidth; ++i) {
         if (hist[WANT_RED]) {
             unsigned int j;
             bool plotted;
             plotted = FALSE;
-            for (j = hist_height - (int)(vscale * hist[WANT_RED][i]); 
-                 j < hist_height && !plotted; 
+            for (j = histHeight - (int)(vscale * hist[WANT_RED][i]); 
+                 j < histHeight && !plotted; 
                  ++j) {
                 PPM_PUTR(pixels[j][i], maxval);
                 plotted = dots;
@@ -406,8 +446,8 @@ ppm_hist(FILE *       const ifP,
             unsigned int j;
             bool plotted;
             plotted = FALSE;
-            for (j = hist_height - (int)(vscale * hist[WANT_GRN][i]); 
-                 j < hist_height && !plotted; 
+            for (j = histHeight - (int)(vscale * hist[WANT_GRN][i]); 
+                 j < histHeight && !plotted; 
                  ++j) {
                 PPM_PUTG(pixels[j][i], maxval);
                 plotted = dots;
@@ -417,33 +457,46 @@ ppm_hist(FILE *       const ifP,
             unsigned int j;
             bool plotted;
             plotted = FALSE;
-            for (j = hist_height - (int)(vscale * hist[WANT_BLU][i]); 
-                 j < hist_height && !plotted; 
+            for (j = histHeight - (int)(vscale * hist[WANT_BLU][i]); 
+                 j < histHeight && !plotted; 
                  ++j) {
                 PPM_PUTB(pixels[j][i], maxval);
                 plotted = dots;
             }
         }
     }
-    ppm_writeppm(stdout, pixels, hist_width, hist_height, maxval, 0);
+    ppm_writeppm(stdout, pixels, histWidth, histHeight, maxval, 0);
+}
+
+
+
+static void
+reportScale(unsigned int const histWidth,
+            unsigned int const range,
+            bool         const verbose) {
+
+    double const hscale = (float)(histWidth-1) / (range-1);
+
+    if (hscale - 1.0 < epsilon && verbose && pm_have_float_format())
+        pm_message("Horizontal scale factor: %g", hscale);
 }
 
 
 
 int
-main(int argc, char ** argv) {
+main(int argc, const char ** argv) {
 
     struct cmdlineInfo cmdline;
     FILE * ifP;
     int cols, rows;
     xelval maxval;
     int format;
-    unsigned int hist_width;
+    unsigned int histWidth;
     unsigned int range;
-    double hscale;
-    int hmax;
+    unsigned int hmax;
+    xelval startval, endval;
 
-    pnm_init (&argc, argv);
+    pm_proginit(&argc, argv);
 
     parseCommandLine(argc, argv, &cmdline);
 
@@ -451,34 +504,33 @@ main(int argc, char ** argv) {
 
     pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
 
-    range = MIN(maxval, cmdline.rval) - cmdline.lval + 1;
+    startval = cmdline.lval;
+    endval   = MIN(maxval, cmdline.rval) + 1;
+
+    range = endval - startval;
 
     if (cmdline.widthSpec)
-        hist_width = cmdline.width;
+        histWidth = cmdline.width;
     else
-        hist_width = range;
-
-    hscale = (float)(hist_width-1) / (range-1);
-    if (hscale - 1.0 < epsilon && cmdline.verbose)
-        pm_message("Horizontal scale factor: %g (maxval = %u)", 
-                   hscale, maxval);
+        histWidth = range;
 
+    reportScale(histWidth, range, cmdline.verbose);
     if (cmdline.nmaxSpec)
-        hmax = cols * rows / hist_width * cmdline.nmax;
+        hmax = cols * rows / histWidth * cmdline.nmax;
 
     switch (PNM_FORMAT_TYPE(format)) {
     case PPM_TYPE:
-        ppm_hist(ifP, cols, rows, maxval, format,
-                 cmdline.dots, cmdline.white, cmdline.black,
-                 cmdline.colorWanted,
-                 cmdline.verbose, cmdline.lval, cmdline.rval, 
-                 hist_width, cmdline.height, cmdline.nmaxSpec, hmax, hscale);
+        ppmHist(ifP, cols, rows, maxval, format,
+                cmdline.dots, cmdline.white, cmdline.black,
+                cmdline.colorWanted,
+                cmdline.verbose, startval, endval,
+                histWidth, cmdline.height, cmdline.nmaxSpec, hmax);
         break;
     case PGM_TYPE:
-        pgm_hist(ifP, cols, rows, maxval, format,
-                 cmdline.dots, cmdline.white, cmdline.black,
-                 cmdline.verbose, cmdline.lval, cmdline.rval,
-                 hist_width, cmdline.height, cmdline.nmaxSpec, hmax, hscale);
+        pgmHist(ifP, cols, rows, maxval, format,
+                cmdline.dots, cmdline.white, cmdline.black,
+                cmdline.verbose, startval, endval,
+                histWidth, cmdline.height, cmdline.nmaxSpec, hmax);
         break;
     case PBM_TYPE:
         pm_error("Cannot do a histogram of a a PBM file");