diff options
Diffstat (limited to 'editor/pamthreshold.c')
-rw-r--r-- | editor/pamthreshold.c | 88 |
1 files changed, 67 insertions, 21 deletions
diff --git a/editor/pamthreshold.c b/editor/pamthreshold.c index a5635790..c5f48147 100644 --- a/editor/pamthreshold.c +++ b/editor/pamthreshold.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <string.h> +#include "pm_c_util.h" #include "mallocvar.h" #include "nstring.h" #include "shhopt.h" @@ -44,10 +45,18 @@ struct cmdlineInfo { /* geometry of local subimage. Defined only if 'local' or 'dual' is true. */ + unsigned int verbose; }; +static __inline__ bool +betweenZeroAndOne(float const arg) { + return (arg >= 0.0 && arg <= 1.0); +} + + + struct range { /* A range of sample values, normalized to [0, 1] */ samplen min; @@ -146,6 +155,8 @@ parseCommandLine(int argc, &thresholdSpec, 0); OPTENT3(0, "contrast", OPT_FLOAT, &cmdlineP->contrast, &contrastSpec, 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, + &cmdlineP->verbose, 0); /* set the defaults */ cmdlineP->width = cmdlineP->height = 0U; @@ -212,6 +223,21 @@ parseCommandLine(int argc, +static void +thresholdPixel(struct pam * const outpamP, + tuplen const inTuplen, + tuple const outTuple, + float const threshold) { + + outTuple[0] = inTuplen[0] >= threshold ? PAM_BW_WHITE : PAM_BLACK; + if (outpamP->depth > 1) { + /* Do alpha */ + outTuple[1] = inTuplen[1] > 0.5 ? 1 : 0; + } +} + + + /* simple thresholding (the same as in pamditherbw) */ static void @@ -230,9 +256,9 @@ thresholdSimple(struct pam * const inpamP, for (row = 0; row < inpamP->height; ++row) { unsigned int col; pnm_readpamrown(inpamP, inrow); - for (col = 0; col < inpamP->width; ++col) - outrow[col][0] = - inrow[col][0] >= threshold ? PAM_BW_WHITE : PAM_BLACK; + for (col = 0; col < inpamP->width; ++col) { + thresholdPixel(outpamP, inrow[col], outrow[col], threshold); + } pnm_writepamrow(outpamP, outrow); } @@ -244,6 +270,7 @@ thresholdSimple(struct pam * const inpamP, static void analyzeDistribution(struct pam * const inpamP, + bool const verbose, const unsigned int ** const histogramP, struct range * const rangeP) { /*---------------------------------------------------------------------------- @@ -255,7 +282,8 @@ analyzeDistribution(struct pam * const inpamP, distribution as *histogramP, an array such that histogram[i] is the number of pixels that have sample value i. - Leave the file positioned to the raster. + Assume the file is positioned to the raster upon entry and leave + it positioned at the same place. -----------------------------------------------------------------------------*/ unsigned int row; tuple * inrow; @@ -295,6 +323,10 @@ analyzeDistribution(struct pam * const inpamP, pnm_freepamrown(inrown); pm_seek2(inpamP->file, &rasterPos, sizeof(rasterPos)); + + if (verbose) + pm_message("Pixel values range from %f to %f", + rangeP->min, rangeP->max); } @@ -342,9 +374,7 @@ computeGlobalThreshold(struct pam * const inpamP, float * const thresholdP) { /*---------------------------------------------------------------------------- Compute the proper threshold to use for the image described by - *inpamP, whose file is positioned to the raster. - - For our convenience: + *inpamP, and: 'histogram' describes the frequency of occurence of the various sample values in the image. @@ -475,6 +505,7 @@ thresholdLocalRow(struct pam * const inpamP, struct cmdlineInfo const cmdline, struct range const globalRange, samplen const globalThreshold, + struct pam * const outpamP, tuple * const outrow) { tuplen * const inrow = inrows[row % windowHeight]; @@ -494,7 +525,7 @@ thresholdLocalRow(struct pam * const inpamP, cmdline.threshold, minSpread, globalThreshold, &threshold); - outrow[col][0] = inrow[col][0] >= threshold ? PAM_BW_WHITE : PAM_BLACK; + thresholdPixel(outpamP, inrow[col], outrow[col], threshold); } } @@ -552,9 +583,16 @@ thresholdLocal(struct pam * const inpamP, windowHeight = MIN(oddLocalHeight, inpamP->height); - analyzeDistribution(inpamP, &histogram, &globalRange); - - computeGlobalThreshold(inpamP, histogram, globalRange, &globalThreshold); + /* global information is needed for dual thresholding */ + if (cmdline.dual) { + analyzeDistribution(inpamP, cmdline.verbose, &histogram, &globalRange); + computeGlobalThreshold(inpamP, histogram, globalRange, + &globalThreshold); + } else { + histogram = NULL; + initRange(&globalRange); + globalThreshold = 1.0; + } outrow = pnm_allocpamrow(outpamP); @@ -574,7 +612,8 @@ thresholdLocal(struct pam * const inpamP, for (row = 0; row < inpamP->height; ++row) { thresholdLocalRow(inpamP, inrows, oddLocalWidth, windowHeight, row, - cmdline, globalRange, globalThreshold, outrow); + cmdline, globalRange, globalThreshold, + outpamP, outrow); pnm_writepamrow(outpamP, outrow); @@ -595,13 +634,14 @@ thresholdLocal(struct pam * const inpamP, static void thresholdIterative(struct pam * const inpamP, - struct pam * const outpamP) { + struct pam * const outpamP, + bool const verbose) { const unsigned int * histogram; struct range globalRange; samplen threshold; - analyzeDistribution(inpamP, &histogram, &globalRange); + analyzeDistribution(inpamP, verbose, &histogram, &globalRange); computeGlobalThreshold(inpamP, histogram, globalRange, &threshold); @@ -624,17 +664,17 @@ main(int argc, char **argv) { parseCommandLine(argc, argv, &cmdline); - if (cmdline.simple) + if (cmdline.simple || cmdline.local) ifP = pm_openr(cmdline.inputFileName); else ifP = pm_openr_seekable(cmdline.inputFileName); - /* threshold each image in the PAM file */ + /* Threshold each image in the PAM file */ eof = FALSE; while (!eof) { pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); - /* set output image parameters for a bilevel image */ + /* Set output image parameters for a bilevel image */ outpam.size = sizeof(outpam); outpam.len = PAM_STRUCT_SIZE(tuple_type); outpam.file = stdout; @@ -642,21 +682,27 @@ main(int argc, char **argv) { outpam.plainformat = 0; outpam.height = inpam.height; outpam.width = inpam.width; - outpam.depth = 1; outpam.maxval = 1; outpam.bytes_per_sample = 1; - strcpy(outpam.tuple_type, "BLACKANDWHITE"); + + if (inpam.depth > 1) { + strcpy(outpam.tuple_type, "BLACKANDWHITE_ALPHA"); + outpam.depth = 2; + } else { + strcpy(outpam.tuple_type, "BLACKANDWHITE"); + outpam.depth = 1; + } pnm_writepaminit(&outpam); - /* do the thresholding */ + /* Do the thresholding */ if (cmdline.simple) thresholdSimple(&inpam, &outpam, cmdline.threshold); else if (cmdline.local || cmdline.dual) thresholdLocal(&inpam, &outpam, cmdline); else - thresholdIterative(&inpam, &outpam); + thresholdIterative(&inpam, &outpam, cmdline.verbose); pnm_nextimage(ifP, &eof); } |