diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:46:26 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2016-03-27 01:46:26 +0000 |
commit | dff6b9fdfeb78fe21a66aa459ddc1d5f7e362dfa (patch) | |
tree | b147568ccffc4cdba9e2a98de1452450ba8e55c3 /analyzer/pnmhistmap.c | |
parent | 4ce684c4978610d1ea42be1b00f7332f3f5f337a (diff) | |
download | netpbm-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.c | 342 |
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"); |