diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2018-03-25 17:14:57 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2018-03-25 17:14:57 +0000 |
commit | cd86a2c8d798c98b2f5d7656971fc4553b4ed172 (patch) | |
tree | 6218a52f6e09f0cb0ff15c0a0b130da920328e8e /editor | |
parent | e488b82f0f446576138084a1bd57b7b4406e8db0 (diff) | |
download | netpbm-mirror-cd86a2c8d798c98b2f5d7656971fc4553b4ed172.tar.gz netpbm-mirror-cd86a2c8d798c98b2f5d7656971fc4553b4ed172.tar.xz netpbm-mirror-cd86a2c8d798c98b2f5d7656971fc4553b4ed172.zip |
Copy Development as new Advanced
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@3186 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor')
-rw-r--r-- | editor/pnmconvol.c | 130 | ||||
-rwxr-xr-x | editor/pnmquant | 20 | ||||
-rw-r--r-- | editor/pnmremap.c | 250 |
3 files changed, 227 insertions, 173 deletions
diff --git a/editor/pnmconvol.c b/editor/pnmconvol.c index d1feb0a3..98ec3a6b 100644 --- a/editor/pnmconvol.c +++ b/editor/pnmconvol.c @@ -169,7 +169,7 @@ getMatrixOptDimensions(const char * const matrixOptString, if (colCt != *widthP) pm_error("-matrix option value contains rows of different " "widths: %u and %u", *widthP, colCt); - } + } pm_strfree(rowString); cursor = next; @@ -211,7 +211,7 @@ parseMatrixRow(const char * const matrixOptRowString, char * trailingJunk; weight[col] = strtod(colString, &trailingJunk); - if (*trailingJunk != '\0') + if (*trailingJunk != '\0') pm_error("The Column %u element of the row '%s' in the " "-matrix value is not a valid floating point " "number", col, matrixOptRowString); @@ -235,7 +235,7 @@ parseMatrixOptWithDimensions(const char * const matrixOptString, unsigned int const width, unsigned int const height, float ** const weight) { - + unsigned int row; const char * cursor; @@ -262,7 +262,7 @@ parseMatrixOptWithDimensions(const char * const matrixOptString, } } } -} +} @@ -311,7 +311,7 @@ parseCommandLine(int argc, char ** argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + and argv. Return the information in the options as *cmdlineP. If command line is internally inconsistent (invalid options, etc.), issue error message to stderr and abort program. @@ -336,9 +336,9 @@ parseCommandLine(int argc, char ** argv, &cmdlineP->matrixSpec, 0) OPTENT3(0, "matrixfile", OPT_STRINGLIST, &cmdlineP->matrixfile, &matrixfileSpec, 0) - OPTENT3(0, "nooffset", OPT_FLAG, NULL, + OPTENT3(0, "nooffset", OPT_FLAG, NULL, &cmdlineP->nooffset, 0); - OPTENT3(0, "normalize", OPT_FLAG, NULL, + OPTENT3(0, "normalize", OPT_FLAG, NULL, &cmdlineP->normalize, 0); OPTENT3(0, "bias", OPT_UINT, &cmdlineP->bias, &biasSpec, 0); @@ -382,7 +382,7 @@ parseCommandLine(int argc, char ** argv, "argument is the input file name"); } else { /* It's an old style invocation we accept for backward compatibility */ - + if (argc-1 < 1) pm_error("You must specify either -matrix or -matrixfile " "at least one argument which names an old-style PGM " @@ -394,7 +394,7 @@ parseCommandLine(int argc, char ** argv, cmdlineP->inputFileName = argv[2]; else cmdlineP->inputFileName = "-"; - + if (argc-1 > 2) pm_error("Too many arguments. Only acceptable arguments are: " "convolution matrix file name and input file name"); @@ -416,11 +416,11 @@ struct ConvKernel { float ** weight[3]; /* weight[PLANE][ROW][COL] is the weight to give to Plane PLANE of the pixel at row ROW, column COL within the convolution window. - + One means full weight. It can have magnitude greater than or less than one. It can be - positive or negative. + positive or negative. */ unsigned int bias; /* The amount to be added to the linear combination of sample values. @@ -441,7 +441,7 @@ warnBadKernel(struct ConvKernel * const convKernelP) { for (plane = 0; plane < convKernelP->planes; ++plane) sum[plane] = 0.0; /* initial value */ - + for (row = 0; row < convKernelP->rows; ++row) { unsigned int col; for (col = 0; col < convKernelP->cols; ++col) { @@ -462,9 +462,9 @@ warnBadKernel(struct ConvKernel * const convKernelP) { if (sum[plane] < 0.0) negative = true; } - + if (biased) { - pm_message("WARNING - this convolution matrix is biased. " + pm_message("WARNING - this convolution matrix is biased. " "red, green, and blue average weights: %f, %f, %f " "(unbiased would be 1).", sum[PAM_RED_PLANE], @@ -488,7 +488,7 @@ warnBadKernel(struct ConvKernel * const convKernelP) { static void convKernelCreatePnm(struct pam * const cpamP, - tuple * const * const ctuples, + tuple * const * const ctuples, unsigned int const depth, bool const offsetPnm, struct ConvKernel ** const convKernelPP) { @@ -526,7 +526,7 @@ convKernelCreatePnm(struct pam * const cpamP, unsigned int row; MALLOCARRAY_NOFAIL(convKernelP->weight[plane], cpamP->height); - + for (row = 0; row < cpamP->height; ++row) { unsigned int col; @@ -578,9 +578,9 @@ normalizeKernelPlane(struct ConvKernel * const convKernelP, for (row = 0, sum = 0.0; row < convKernelP->rows; ++row) { unsigned int col; - + for (col = 0; col < convKernelP->cols; ++col) { - + sum += convKernelP->weight[plane][row][col]; } } @@ -592,7 +592,7 @@ normalizeKernelPlane(struct ConvKernel * const convKernelP, for (row = 0; row < convKernelP->rows; ++row) { unsigned int col; - + for (col = 0; col < convKernelP->cols; ++col) convKernelP->weight[plane][row][col] *= scaler; } @@ -641,7 +641,7 @@ getKernelPnm(const char * const fileName, /* Read in the convolution matrix. */ ctuples = pnm_readpam(cifP, &cpam, PAM_STRUCT_SIZE(tuple_type)); pm_close(cifP); - + validateKernelDimensions(cpam.width, cpam.height); convKernelCreatePnm(&cpam, ctuples, depth, offset, convKernelPP); @@ -657,7 +657,7 @@ convKernelCreateMatrixOpt(struct matrixOpt const matrixOpt, /*---------------------------------------------------------------------------- Create a convolution kernel as described by a -matrix command line option. - + The option value is 'matrixOpt'. -----------------------------------------------------------------------------*/ struct ConvKernel * convKernelP; @@ -678,7 +678,7 @@ convKernelCreateMatrixOpt(struct matrixOpt const matrixOpt, MALLOCARRAY_NOFAIL(convKernelP->weight[plane][row], matrixOpt.width); - + for (col = 0; col < matrixOpt.width; ++col) convKernelP->weight[plane][row][col] = matrixOpt.weight[row][col]; @@ -728,7 +728,7 @@ parsePlaneFileLine(const char * const line, else { char * trailingJunk; weight[colCt] = strtod(token, &trailingJunk); - if (*trailingJunk != '\0') + if (*trailingJunk != '\0') pm_error("The Column %u element of the row '%s' in the " "-matrix value is not a valid floating point " "number", colCt, line); @@ -744,7 +744,7 @@ parsePlaneFileLine(const char * const line, static void -readPlaneFile(FILE * const ifP, +readPlaneFile(FILE * const ifP, float *** const weightP, unsigned int * const widthP, unsigned int * const heightP) { @@ -783,7 +783,7 @@ readPlaneFile(FILE * const ifP, eof = true; else { REALLOCARRAY(weight, rowCt + 1); - + if (weight == NULL) pm_error("Unable to allocate memory for " "convolution matrix"); @@ -799,7 +799,7 @@ readPlaneFile(FILE * const ifP, pm_error("Multiple row widths in the convolution " "matrix file: %u columns and %u columns.", width, thisWidth); - } + } ++rowCt; } pm_strfree(line); @@ -818,7 +818,7 @@ readPlaneFile(FILE * const ifP, static void copyWeight(float ** const srcWeight, unsigned int const width, - unsigned int const height, + unsigned int const height, float *** const dstWeightP) { /*---------------------------------------------------------------------------- Make a copy, in dynamically allocated memory, of the weight matrix @@ -832,7 +832,7 @@ copyWeight(float ** const srcWeight, if (dstWeight == NULL) pm_error("Could not allocate memory for convolution matrix"); - + for (row = 0; row < height; ++row) { unsigned int col; @@ -973,7 +973,7 @@ validateEnoughImageToConvolve(const struct pam * const inpamP, pm_error("Image is too short (%u rows) to convolve with this " "%u-row convolution kernel.", inpamP->height, convKernelP->rows); - + if (inpamP->width < convKernelP->cols + 1) pm_error("Image is too narrow (%u columns) to convolve with this " "%u-column convolution kernel.", @@ -994,7 +994,7 @@ allocRowbuf(struct pam * const pamP, pm_error("Failed to allocate %u-row buffer", height); else { unsigned int row; - + for (row = 0; row < height; ++row) rowbuf[row] = pnm_allocpamrow(pamP); } @@ -1043,7 +1043,7 @@ readAndScaleRows(struct pam * const inpamP, unsigned int const outputDepth) { /*---------------------------------------------------------------------------- Read in 'count' rows into rowbuf[]. - + Scale the contents to maxval 'outputMaxval' and expand to depth 'outputDepth'. -----------------------------------------------------------------------------*/ @@ -1173,7 +1173,7 @@ convolveGeneralRowPlane(struct pam * const pamP, unsigned int const ccolso2 = convKernelP->cols / 2; unsigned int col; - + for (col = 0; col < pamP->width; ++col) { if (col < ccolso2 || col >= pamP->width - ccolso2) /* The unconvolved left or right edge */ @@ -1283,7 +1283,7 @@ allocSum(unsigned int const depth, for (plane = 0; plane < depth; ++plane) { MALLOCARRAY(sum[plane], size); - + if (!sum[plane]) pm_error("Could not allocate memory for %u sums", size); } @@ -1330,7 +1330,7 @@ computeInitialColumnSums(struct pam * const pamP, row < convKernelP->rows; ++row) convColumnSum[plane][col] += window[row][col][plane]; - } + } } } @@ -1358,7 +1358,7 @@ convolveRowWithColumnSumsMean(const struct ConvKernel * const convKernelP, be convolved because the convolution window runs off the edge). -----------------------------------------------------------------------------*/ unsigned int plane; - + for (plane = 0; plane < pamP->depth; ++plane) { unsigned int const crowso2 = convKernelP->rows / 2; unsigned int const ccolso2 = convKernelP->cols / 2; @@ -1385,7 +1385,7 @@ convolveRowWithColumnSumsMean(const struct ConvKernel * const convKernelP, } else { /* Column numbers to subtract or add to isum */ unsigned int const subcol = col - ccolso2 - 1; - unsigned int const addcol = col + ccolso2; + unsigned int const addcol = col + ccolso2; gisum -= convColumnSum[plane][subcol]; gisum += convColumnSum[plane][addcol]; @@ -1429,7 +1429,7 @@ convolveRowWithColumnSumsVertical( for (plane = 0; plane < pamP->depth; ++plane) { unsigned int col; - + for (col = 0; col < pamP->width; ++col) { if (col < ccolso2 || col >= pamP->width - ccolso2) { /* The unconvolved left or right edge */ @@ -1513,12 +1513,12 @@ convolveMeanRowPlane(struct pam * const pamP, } else { /* Column numbers to subtract or add to isum */ unsigned int const subcol = col - ccolso2 - 1; - unsigned int const addcol = col + ccolso2; - + unsigned int const addcol = col + ccolso2; + convColumnSum[addcol] = convColumnSum[addcol] - window[subrow][addcol][plane] + window[addrow][addcol][plane]; - + gisum = gisum - convColumnSum[subcol] + convColumnSum[addcol]; } outputrow[col][plane] = @@ -1674,7 +1674,7 @@ allocRowSum(unsigned int const depth, for (plane = 0; plane < depth; ++plane) { MALLOCARRAY(sum[plane], height); - + if (!sum[plane]) pm_error("Could not allocate memory for %u rows of sums", height); @@ -1683,7 +1683,7 @@ allocRowSum(unsigned int const depth, for (row = 0; row < height; ++row) { MALLOCARRAY(sum[plane][row], width); - + if (!sum[plane][row]) pm_error("Could not allocate memory " "for a row of sums"); @@ -1747,7 +1747,7 @@ convolveHorizontalRowPlane0(struct pam * const outpamP, starts at the left edge of the image. */ unsigned int const leftcol = 0; - + unsigned int crow; for (crow = 0, matrixSum = 0.0; @@ -1756,7 +1756,7 @@ convolveHorizontalRowPlane0(struct pam * const outpamP, tuple * const tuplesInWindow = &window[crow][leftcol]; unsigned int ccol; - + sumWindow[crow][col] = 0; for (ccol = 0; ccol < convKernelP->cols; ++ccol) sumWindow[crow][col] += tuplesInWindow[ccol][plane]; @@ -1769,7 +1769,7 @@ convolveHorizontalRowPlane0(struct pam * const outpamP, unsigned int const addcol = col + ccolso2; unsigned int crow; - + for (crow = 0, matrixSum = 0.0; crow < convKernelP->rows; ++crow) { @@ -1798,7 +1798,7 @@ setupCircMap2(tuple ** const rowbuf, unsigned int const windowHeight) { unsigned int const toprow = windowTopRow % windowHeight; - + unsigned int crow; unsigned int i; @@ -1874,7 +1874,7 @@ convolveHorizontalRowPlane(struct pam * const pamP, } } else { unsigned int const subcol = col - ccolso2 - 1; - unsigned int const addcol = col + ccolso2; + unsigned int const addcol = col + ccolso2; unsigned int crow; @@ -1947,7 +1947,7 @@ convolveHorizontal(struct pam * const inpamP, for (crow = 0; crow < convKernelP->rows; ++crow) sumCircMap[crow] = convRowSum[plane][crow]; - + convolveHorizontalRowPlane0(outpamP, circMap, convKernelP, plane, outputrow, sumCircMap); } @@ -1969,13 +1969,13 @@ convolveHorizontal(struct pam * const inpamP, readAndScaleRow(inpamP, rowbuf[windowBotRow % windowHeight], outpamP->maxval, outpamP->depth); - + setupCircMap2(rowbuf, convRowSum[plane], circMap, sumCircMap, windowTopRow, windowHeight); convolveHorizontalRowPlane(outpamP, circMap, convKernelP, plane, outputrow, sumCircMap); - + pnm_writepamrow(outpamP, outputrow); } } @@ -2005,7 +2005,7 @@ convolveVerticalRowPlane(struct pam * const pamP, */ unsigned int const addrow = 1 + (convKernelP->rows - 1); /* Bottom row of convolution window: What we add to running sum */ - + unsigned int col; for (col = 0; col < pamP->width; ++col) { @@ -2304,7 +2304,7 @@ main(int argc, char * argv[]) { original) in January 1995. Reduce run time by general optimizations and handling special cases of - convolution matrices. Program automatically determines if convolution + convolution matrices. Program automatically determines if convolution matrix is one of the types it can make use of so no extra command line arguments are necessary. @@ -2322,7 +2322,7 @@ main(int argc, char * argv[]) { ------------------------------------------- Created separate functions as code was getting too large to put keep both PGM and PPM cases in same function and also because SWITCH statement in - inner loop can take progressively more time the larger the size of the + inner loop can take progressively more time the larger the size of the convolution matrix. GCC is affected this way. Removed use of MOD (%) operator from innermost loop by modifying manner in @@ -2331,50 +2331,50 @@ main(int argc, char * argv[]) { This is from the file pnmconvol.README, dated August 1995, extracted in April 2000, which was in the March 1994 Netpbm release: - ----------------------------------------------------------------------------- + ----------------------------------------------------------------------------- This is a faster version of the pnmconvol.c program that comes with netpbm. There are no changes to the command line arguments, so this program can be dropped in without affecting the way you currently run it. An updated man page is also included. - + My original intention was to improve the running time of applying a neighborhood averaging convolution matrix to an image by using a different algorithm, but I also improved the run time of performing the general convolution by optimizing that code. The general convolution runs in 1/4 to 1/2 of the original time and neighborhood averaging runs in near constant time for the convolution masks I tested (3x3, 5x5, 7x7, 9x9). - + Sample times for two computers are below. Times are in seconds as reported by /bin/time for a 512x512 pgm image. - + Matrix IBM RS6000 SUN IPC Size & Type 220 - + 3x3 original pnmconvol 6.3 18.4 new general case 3.1 6.0 new average case 1.8 2.6 - + 5x5 original pnmconvol 11.9 44.4 new general case 5.6 11.9 new average case 1.8 2.6 - + 7x7 original pnmconvol 20.3 82.9 new general case 9.4 20.7 new average case 1.8 2.6 - + 9x9 original pnmconvol 30.9 132.4 new general case 14.4 31.8 new average case 1.8 2.6 - - + + Send all questions/comments/bugs to me at burns@chem.psu.edu. - + - Mike - + ---------------------------------------------------------------------------- Mike Burns System Administrator burns@chem.psu.edu Department of Chemistry diff --git a/editor/pnmquant b/editor/pnmquant index 35a75e96..0bb328d2 100755 --- a/editor/pnmquant +++ b/editor/pnmquant @@ -96,6 +96,8 @@ sub parseCommandLine(@) { "spreadbrightness", "spreadluminosity", "floyd|fs!", + "norandom", + "randomseed=i", "quiet", "plain"); @@ -248,9 +250,10 @@ sub makeColormap($$$$$) { -sub remap($$$$) { +sub remap($$$$$$) { - my ($mapfileSpec, $opt_floyd, $opt_plain, $opt_quiet) = @_; + my ($mapfileSpec, $opt_floyd, $opt_norandom, $opt_randomseed, + $opt_plain, $opt_quiet) = @_; # Remap the image on Standard Input to Standard Output, using the colors # from the colormap file named $mapfileSpec. @@ -261,6 +264,17 @@ sub remap($$$$) { if ($opt_floyd) { push(@options, "-floyd"); } + if ($opt_norandom) { + push(@options, "-norandom"); + } + if (defined($opt_randomseed)) { + if ($opt_randomseed < 0) { + print(STDERR "-randomseed value must not be negative. " . + "You specified $opt_randomseed\n"); + exit(10); + } + push(@options, "-randomseed=$opt_randomseed"); + } if ($opt_plain) { push(@options, "-plain"); } @@ -311,6 +325,8 @@ open(STDOUT, ">&OLDOUT"); remap($mapfileSpec, $cmdlineR->{floyd}, + $cmdlineR->{norandom}, + $cmdlineR->{randomseed}, $cmdlineR->{plain}, $cmdlineR->{quiet}); diff --git a/editor/pnmremap.c b/editor/pnmremap.c index ed758aa3..59b1e84b 100644 --- a/editor/pnmremap.c +++ b/editor/pnmremap.c @@ -41,6 +41,17 @@ enum MissingMethod { MISSING_CLOSE }; +enum InitRandom { + RANDOM_NONE, + RANDOM_WITHSEED, + RANDOM_NOSEED +}; + +struct Random { + enum InitRandom init; + unsigned int seed; +}; + struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. @@ -48,9 +59,9 @@ struct CmdlineInfo { const char * inputFilespec; /* Filespec of input file */ const char * mapFilespec; /* Filespec of colormap file */ unsigned int floyd; /* Boolean: -floyd/-fs option */ - unsigned int norandom; + struct Random random; enum MissingMethod missingMethod; - char * missingcolor; + char * missingcolor; /* -missingcolor value. Null if not specified */ unsigned int verbose; }; @@ -62,7 +73,7 @@ parseCommandLine (int argc, const char ** argv, struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + and argv. Return the information in the options as *cmdlineP. If command line is internally inconsistent (invalid options, etc.), issue error message to stderr and abort program. @@ -78,28 +89,30 @@ parseCommandLine (int argc, const char ** argv, unsigned int option_def_index; unsigned int nofloyd, firstisdefault; - unsigned int missingSpec, mapfileSpec; + unsigned int missingSpec, mapfileSpec, norandomSpec, randomseedSpec; MALLOCARRAY_NOFAIL(option_def, 100); - + option_def_index = 0; /* incremented by OPTENT3 */ - OPTENT3(0, "floyd", OPT_FLAG, + OPTENT3(0, "floyd", OPT_FLAG, NULL, &cmdlineP->floyd, 0); - OPTENT3(0, "fs", OPT_FLAG, + OPTENT3(0, "fs", OPT_FLAG, NULL, &cmdlineP->floyd, 0); - OPTENT3(0, "nofloyd", OPT_FLAG, + OPTENT3(0, "nofloyd", OPT_FLAG, NULL, &nofloyd, 0); - OPTENT3(0, "nofs", OPT_FLAG, + OPTENT3(0, "nofs", OPT_FLAG, NULL, &nofloyd, 0); - OPTENT3(0, "norandom", OPT_FLAG, - NULL, &cmdlineP->norandom, 0); - OPTENT3(0, "firstisdefault", OPT_FLAG, + OPTENT3(0, "norandom", OPT_FLAG, + NULL, &norandomSpec, 0); + OPTENT3(0, "randomseed", OPT_UINT, + &cmdlineP->random.seed, &randomseedSpec, 0); + OPTENT3(0, "firstisdefault", OPT_FLAG, NULL, &firstisdefault, 0); - OPTENT3(0, "mapfile", OPT_STRING, + OPTENT3(0, "mapfile", OPT_STRING, &cmdlineP->mapFilespec, &mapfileSpec, 0); - OPTENT3(0, "missingcolor", OPT_STRING, + OPTENT3(0, "missingcolor", OPT_STRING, &cmdlineP->missingcolor, &missingSpec, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); opt.opt_table = option_def; @@ -107,13 +120,32 @@ parseCommandLine (int argc, const char ** argv, opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ cmdlineP->missingcolor = NULL; /* default value */ - + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ if (cmdlineP->floyd && nofloyd) pm_error("You cannot specify both -floyd and -nofloyd options."); + if (cmdlineP->floyd) { + if (norandomSpec) { + if (randomseedSpec) + pm_error("You cannot specify both -norandom and -randomseed."); + else + cmdlineP->random.init = RANDOM_NONE; + } else { + if (randomseedSpec) + cmdlineP->random.init = RANDOM_WITHSEED; + else + cmdlineP->random.init = RANDOM_NOSEED; + } + } else { + if (norandomSpec) + pm_message("-floyd not specified. -norandom has no effect."); + if (randomseedSpec) + pm_message("-floyd not specified. Ignoring -randomseed value."); + } + if (firstisdefault && missingSpec) pm_error("You cannot specify both -missing and -firstisdefault."); @@ -176,7 +208,7 @@ grayscaleToDepth3(tuple const tuple) { static void adjustDepthTuple(tuple const tuple, depthAdjustment const adjustment) { - + switch (adjustment) { case ADJUST_NONE: break; @@ -194,7 +226,7 @@ adjustDepthTuple(tuple const tuple, static void inverseAdjustDepthTuple(tuple const tuple, depthAdjustment const adjustment) { - + switch (adjustment) { case ADJUST_NONE: break; @@ -249,7 +281,7 @@ selectDepthAdjustment(const struct pam * const pamP, The only depth changes we know how to do are: - - from tuple type RGB, depth 3 to depth 1 + - from tuple type RGB, depth 3 to depth 1 We change it to grayscale or black and white. @@ -296,7 +328,7 @@ selectDepthAdjustment(const struct pam * const pamP, "that I know how to convert to the map depth. " "I can convert RGB, GRAYSCALE, and BLACKANDWHITE. " "The input image is '%.*s'.", - newDepth, pamP->depth, + newDepth, pamP->depth, (int)sizeof(pamP->tuple_type), pamP->tuple_type); } } @@ -305,8 +337,8 @@ selectDepthAdjustment(const struct pam * const pamP, static void -computeColorMapFromMap(struct pam * const mappamP, - tuple ** const maptuples, +computeColorMapFromMap(struct pam * const mappamP, + tuple ** const maptuples, tupletable * const colormapP, unsigned int * const newcolorsP) { /*---------------------------------------------------------------------------- @@ -317,12 +349,12 @@ computeColorMapFromMap(struct pam * const mappamP, Return the number of colors in the returned colormap as *newcolorsP. -----------------------------------------------------------------------------*/ - unsigned int colors; + unsigned int colors; if (mappamP->width == 0 || mappamP->height == 0) pm_error("colormap file contains no pixels"); - *colormapP = + *colormapP = pnm_computetuplefreqtable(mappamP, maptuples, MAXCOLORS, &colors); if (*colormapP == NULL) pm_error("too many colors in colormap!"); @@ -334,7 +366,7 @@ computeColorMapFromMap(struct pam * const mappamP, #define FS_SCALE 1024 -struct fserr { +struct Fserr { unsigned int width; /* Width of the image being dithered */ long ** thiserr; @@ -359,20 +391,26 @@ struct fserr { static void -randomizeError(long ** const err, - unsigned int const width, - unsigned int const depth) { +randomizeError(long ** const err, + unsigned int const width, + unsigned int const depth, + struct Random const random) { /*---------------------------------------------------------------------------- Set a random error in the range [-1 .. 1] (normalized via FS_SCALE) in the error array err[][]. -----------------------------------------------------------------------------*/ + unsigned int const seed = (random.init == RANDOM_WITHSEED) ? + random.seed : pm_randseed(); + unsigned int col; - srand(pm_randseed()); + assert(random.init != RANDOM_NONE); + + srand(seed); for (col = 0; col < width; ++col) { unsigned int plane; - for (plane = 0; plane < depth; ++plane) + for (plane = 0; plane < depth; ++plane) err[plane][col] = rand() % (FS_SCALE * 2) - FS_SCALE; } } @@ -390,7 +428,7 @@ zeroError(long ** const err, for (col = 0; col < width; ++col) { unsigned int plane; - for (plane = 0; plane < depth; ++plane) + for (plane = 0; plane < depth; ++plane) err[plane][col] = 0; } } @@ -398,7 +436,7 @@ zeroError(long ** const err, static void -fserrSetForward(struct fserr * const fserrP) { +fserr_setForward(struct Fserr * const fserrP) { fserrP->fsForward = TRUE; fserrP->begCol = 0; @@ -409,7 +447,7 @@ fserrSetForward(struct fserr * const fserrP) { static void -fserrSetBackward(struct fserr * const fserrP) { +fserr_setBackward(struct Fserr * const fserrP) { fserrP->fsForward = FALSE; fserrP->begCol = fserrP->width - 1; @@ -420,9 +458,9 @@ fserrSetBackward(struct fserr * const fserrP) { static void -initFserr(struct pam * const pamP, - struct fserr * const fserrP, - bool const initRandom) { +fserr_init(struct pam * const pamP, + struct Fserr * const fserrP, + struct Random const random) { /*---------------------------------------------------------------------------- Initialize the Floyd-Steinberg error vectors -----------------------------------------------------------------------------*/ @@ -440,7 +478,7 @@ initFserr(struct pam * const pamP, if (fserrP->nexterr == NULL) pm_error("Out of memory allocating Floyd-Steinberg structures " "for depth %u", pamP->depth); - + for (plane = 0; plane < pamP->depth; ++plane) { MALLOCARRAY(fserrP->thiserr[plane], fserrSize); if (fserrP->thiserr[plane] == NULL) @@ -452,24 +490,24 @@ initFserr(struct pam * const pamP, "for Plane %u, size %u", plane, fserrSize); } - if (initRandom) - randomizeError(fserrP->thiserr, fserrSize, pamP->depth); + if (random.init != RANDOM_NONE) + randomizeError(fserrP->thiserr, fserrSize, pamP->depth, random); else zeroError(fserrP->thiserr, fserrSize, pamP->depth); - fserrSetForward(fserrP); + fserr_setForward(fserrP); } static void -floydInitRow(struct pam * const pamP, struct fserr * const fserrP) { +floydInitRow(struct pam * const pamP, struct Fserr * const fserrP) { int col; - + for (col = 0; col < pamP->width + 2; ++col) { unsigned int plane; - for (plane = 0; plane < pamP->depth; ++plane) + for (plane = 0; plane < pamP->depth; ++plane) fserrP->nexterr[plane][col] = 0; } } @@ -477,10 +515,10 @@ floydInitRow(struct pam * const pamP, struct fserr * const fserrP) { static void -floydAdjustColor(struct pam * const pamP, - tuple const intuple, - tuple const outtuple, - struct fserr * const fserrP, +floydAdjustColor(struct pam * const pamP, + tuple const intuple, + tuple const outtuple, + struct Fserr * const fserrP, int const col) { /*---------------------------------------------------------------------------- Use Floyd-Steinberg errors to adjust actual color. @@ -497,10 +535,10 @@ floydAdjustColor(struct pam * const pamP, static void -floydPropagateErr(struct pam * const pamP, - struct fserr * const fserrP, - int const col, - tuple const oldtuple, +floydPropagateErr(struct pam * const pamP, + struct Fserr * const fserrP, + int const col, + tuple const oldtuple, tuple const newtuple) { /*---------------------------------------------------------------------------- Propagate Floyd-Steinberg error terms. @@ -515,7 +553,7 @@ floydPropagateErr(struct pam * const pamP, long const newSample = newtuple[plane]; long const oldSample = oldtuple[plane]; long const err = (oldSample - newSample) * FS_SCALE; - + if (fserrP->fsForward) { fserrP->thiserr[plane][col + 2] += ( err * 7 ) / 16; fserrP->nexterr[plane][col ] += ( err * 3 ) / 16; @@ -533,7 +571,7 @@ floydPropagateErr(struct pam * const pamP, static void -floydSwitchDir(struct pam * const pamP, struct fserr * const fserrP) { +floydSwitchDir(struct pam * const pamP, struct Fserr * const fserrP) { unsigned int plane; @@ -544,9 +582,9 @@ floydSwitchDir(struct pam * const pamP, struct fserr * const fserrP) { } if (fserrP->fsForward) - fserrSetBackward(fserrP); + fserr_setBackward(fserrP); else - fserrSetForward(fserrP); + fserr_setForward(fserrP); } @@ -567,7 +605,7 @@ struct colormapFinder { /* The value by which our intermediate distance calculations have to be divided to make sure we don't overflow our unsigned int data structure. - + To the extent 'distanceDivider' is greater than 1, closest color results will be approximate -- there could conceivably be a closer one that we miss. @@ -590,13 +628,13 @@ createColormapFinder(struct pam * const pamP, colormapFinderP->colors = colors; { - unsigned int const maxHandleableSqrDiff = + unsigned int const maxHandleableSqrDiff = (unsigned int)UINT_MAX / pamP->depth; - + if (SQR(pamP->maxval) > maxHandleableSqrDiff) colormapFinderP->distanceDivider = (unsigned int) (SQR(pamP->maxval) / maxHandleableSqrDiff + 0.1 + 1.0); - /* The 0.1 is a fudge factor to keep us out of rounding + /* The 0.1 is a fudge factor to keep us out of rounding trouble. The 1.0 effects a round-up. */ else @@ -664,8 +702,8 @@ searchColormapClose(struct pam * const pamP, newdist = 0; for (plane=0; plane < pamP->depth; ++plane) { - newdist += - SQR(tuple[plane] - colorFinderP->colormap[i]->tuple[plane]) + newdist += + SQR(tuple[plane] - colorFinderP->colormap[i]->tuple[plane]) / colorFinderP->distanceDivider; } if (newdist < dist) { @@ -695,15 +733,15 @@ searchColormapExact(struct pam * const pamP, -----------------------------------------------------------------------------*/ unsigned int i; bool found; - + found = FALSE; /* initial value */ for (i = 0; i < colorFinderP->colors && !found; ++i) { unsigned int plane; found = TRUE; /* initial assumption */ - for (plane=0; plane < pamP->depth; ++plane) - if (tuple[plane] != colorFinderP->colormap[i]->tuple[plane]) + for (plane=0; plane < pamP->depth; ++plane) + if (tuple[plane] != colorFinderP->colormap[i]->tuple[plane]) found = FALSE; - if (found) + if (found) *colormapIndexP = i; } *foundP = found; @@ -712,11 +750,11 @@ searchColormapExact(struct pam * const pamP, static void -lookupThroughHash(struct pam * const pamP, - tuple const tuple, +lookupThroughHash(struct pam * const pamP, + tuple const tuple, bool const needExactMatch, struct colormapFinder * const colorFinderP, - tuplehash const colorhash, + tuplehash const colorhash, int * const colormapIndexP, bool * const usehashP) { /*---------------------------------------------------------------------------- @@ -748,11 +786,11 @@ lookupThroughHash(struct pam * const pamP, colormapIndexP, &found); if (!found) *colormapIndexP = -1; - } else + } else searchColormapClose(pamP, tuple, colorFinderP, colormapIndexP); if (*usehashP) { int fits; - pnm_addtotuplehash(pamP, colorhash, tuple, *colormapIndexP, + pnm_addtotuplehash(pamP, colorhash, tuple, *colormapIndexP, &fits); if (!fits) { pm_message("out of memory adding to hash table; " @@ -771,7 +809,7 @@ mapTuple(struct pam * const pamP, tuple const defaultColor, tupletable const colormap, struct colormapFinder * const colorFinderP, - tuplehash const colorhash, + tuplehash const colorhash, bool * const usehashP, tuple const outTuple, bool * const missingP) { @@ -781,7 +819,7 @@ mapTuple(struct pam * const pamP, there is no usable color in the color map. */ - lookupThroughHash(pamP, inTuple, !!defaultColor, colorFinderP, + lookupThroughHash(pamP, inTuple, !!defaultColor, colorFinderP, colorhash, &colormapIndex, usehashP); if (colormapIndex == -1) { @@ -800,12 +838,12 @@ mapTuple(struct pam * const pamP, static void convertRowStraight(struct pam * const inpamP, - struct pam * const outpamP, + struct pam * const outpamP, tuple inrow[], depthAdjustment const depthAdjustment, tupletable const colormap, struct colormapFinder * const colorFinderP, - tuplehash const colorhash, + tuplehash const colorhash, bool * const usehashP, tuple const defaultColor, tuple outrow[], @@ -822,7 +860,7 @@ convertRowStraight(struct pam * const inpamP, -----------------------------------------------------------------------------*/ unsigned int col; unsigned int missingCount; - + /* The following modify tuplerow, to make it consistent with *outpamP instead of *inpamP. */ @@ -833,7 +871,7 @@ convertRowStraight(struct pam * const inpamP, adjustDepthRow(outrow, outpamP->width, depthAdjustment); missingCount = 0; /* initial value */ - + for (col = 0; col < outpamP->width; ++col) { bool missing; mapTuple(outpamP, outrow[col], defaultColor, @@ -856,10 +894,10 @@ convertRowDither(struct pam * const inpamP, depthAdjustment const depthAdjustment, tupletable const colormap, struct colormapFinder * const colorFinderP, - tuplehash const colorhash, + tuplehash const colorhash, bool * const usehashP, tuple const defaultColor, - struct fserr * const fserrP, + struct Fserr * const fserrP, tuple outrow[], unsigned int * const missingCountP) { /*---------------------------------------------------------------------------- @@ -885,7 +923,7 @@ convertRowDither(struct pam * const inpamP, floydInitRow(inpamP, fserrP); missingCount = 0; /* initial value */ - + for (col = fserrP->begCol; col != fserrP->endCol; col += fserrP->step) { bool missing; @@ -929,11 +967,11 @@ convertRow(struct pam * const inpamP, depthAdjustment depthAdjustment, tupletable const colormap, struct colormapFinder * const colorFinderP, - tuplehash const colorhash, + tuplehash const colorhash, bool * const usehashP, - bool const floyd, + bool const floyd, tuple const defaultColor, - struct fserr * const fserrP, + struct Fserr * const fserrP, tuple outrow[], unsigned int * const missingCountP) { /*---------------------------------------------------------------------------- @@ -959,7 +997,7 @@ convertRow(struct pam * const inpamP, depthAdjustment, colormap, colorFinderP, colorhash, usehashP, defaultColor, fserrP, outrow, missingCountP); - else + else convertRowStraight(inpamP, outpamP, inrow, depthAdjustment, colormap, colorFinderP, colorhash, usehashP, defaultColor, @@ -969,14 +1007,14 @@ convertRow(struct pam * const inpamP, static void -copyRaster(struct pam * const inpamP, - struct pam * const outpamP, - tupletable const colormap, - unsigned int const colormapSize, - bool const floyd, - bool const randomize, - tuple const defaultColor, - unsigned int * const missingCountP) { +copyRaster(struct pam * const inpamP, + struct pam * const outpamP, + tupletable const colormap, + unsigned int const colormapSize, + bool const floyd, + struct Random const random, + tuple const defaultColor, + unsigned int * const missingCountP) { tuplehash const colorhash = pnm_createtuplehash(); @@ -992,7 +1030,7 @@ copyRaster(struct pam * const inpamP, depthAdjustment depthAdjustment; struct colormapFinder * colorFinderP; bool usehash; - struct fserr fserr; + struct Fserr fserr; int row; workpam = *outpamP; @@ -1017,7 +1055,7 @@ copyRaster(struct pam * const inpamP, createColormapFinder(outpamP, colormap, colormapSize, &colorFinderP); if (floyd) - initFserr(inpamP, &fserr, randomize); + fserr_init(inpamP, &fserr, random); *missingCountP = 0; /* initial value */ @@ -1030,9 +1068,9 @@ copyRaster(struct pam * const inpamP, depthAdjustment, colormap, colorFinderP, colorhash, &usehash, floyd, defaultColor, &fserr, outrow, &missingCount); - + *missingCountP += missingCount; - + pnm_writepamrow(outpamP, outrow); } destroyColormapFinder(colorFinderP); @@ -1046,10 +1084,10 @@ copyRaster(struct pam * const inpamP, static void remap(FILE * const ifP, const struct pam * const outpamCommonP, - tupletable const colormap, + tupletable const colormap, unsigned int const colormapSize, bool const floyd, - bool const randomize, + struct Random const random, tuple const defaultColor, bool const verbose) { /*---------------------------------------------------------------------------- @@ -1075,7 +1113,7 @@ remap(FILE * const ifP, */ pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(allocation_depth)); - + outpam = *outpamCommonP; outpam.width = inpam.width; outpam.height = inpam.height; @@ -1086,13 +1124,13 @@ remap(FILE * const ifP, convert the input to the output depth. */ pnm_setminallocationdepth(&inpam, outpam.depth); - + copyRaster(&inpam, &outpam, colormap, colormapSize, floyd, - randomize, defaultColor, &missingCount); - + random, defaultColor, &missingCount); + if (verbose) pm_message("%u pixels not matched in color map", missingCount); - + pnm_nextimage(ifP, &eof); } } @@ -1130,7 +1168,7 @@ processMapFile(const char * const mapFileName, pnm_freepamarray(maptuples, &mappam); - *outpamCommonP = mappam; + *outpamCommonP = mappam; outpamCommonP->file = stdout; } @@ -1142,7 +1180,7 @@ getSpecifiedMissingColor(struct pam * const pamP, tuple * const specColorP) { tuple specColor; - + specColor = pnm_allocpamtuple(pamP); if (colorName) { @@ -1213,8 +1251,8 @@ main(int argc, const char * argv[] ) { break; } - remap(ifP, &outpamCommon, colormap, colormapSize, - cmdline.floyd, !cmdline.norandom, defaultColor, + remap(ifP, &outpamCommon, colormap, colormapSize, + cmdline.floyd, cmdline.random, defaultColor, cmdline.verbose); pnm_freepamtuple(firstColor); |