diff options
Diffstat (limited to 'editor/ppmchange.c')
-rw-r--r-- | editor/ppmchange.c | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/editor/ppmchange.c b/editor/ppmchange.c index dea85a77..cfc34769 100644 --- a/editor/ppmchange.c +++ b/editor/ppmchange.c @@ -19,20 +19,22 @@ #include "mallocvar.h" #define TCOLS 256 -#define SQRT3 1.73205080756887729352 +static double const sqrt3 = 1.73205080756887729352; /* The square root of 3 */ +static double const EPSILON = 1.0e-5; -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char *input_filespec; /* Filespecs of input files */ int ncolors; /* Number of valid entries in color0[], color1[] */ - char * oldcolorname[TCOLS]; /* colors user wants replaced */ - char * newcolorname[TCOLS]; /* colors with which he wants them replaced */ - int closeness; - /* -closeness option value. Zero if no -closeness option */ - char * remainder_colorname; + const char * oldcolorname[TCOLS]; + /* colors user wants replaced */ + const char * newcolorname[TCOLS]; + /* colors with which he wants them replaced */ + float closeness; + const char * remainder_colorname; /* Color user specified for -remainder. Null pointer if he didn't specify -remainder. */ @@ -42,8 +44,8 @@ struct cmdlineInfo { static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { +parseCommandLine(int argc, const char ** const argv, + struct CmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. @@ -59,7 +61,7 @@ parseCommandLine(int argc, char ** argv, MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENTRY */ - OPTENT3(0, "closeness", OPT_UINT, + OPTENT3(0, "closeness", OPT_FLOAT, &cmdlineP->closeness, &closenessSpec, 0); OPTENT3(0, "remainder", OPT_STRING, &cmdlineP->remainder_colorname, &remainderSpec, 0); @@ -70,15 +72,22 @@ 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 */ - pm_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 (!remainderSpec) cmdlineP->remainder_colorname = NULL; if (!closenessSpec) - cmdlineP->closeness = 0; + cmdlineP->closeness = 0.0; + if (cmdlineP->closeness < 0.0) + pm_error("-closeness value %f is negative", cmdlineP->closeness); + + if (cmdlineP->closeness > 100) + pm_error("-closeness value %f is more than 100%%", + cmdlineP->closeness); + if ((argc-1) % 2 == 0) cmdlineP->input_filespec = "-"; else @@ -99,26 +108,19 @@ parseCommandLine(int argc, char ** argv, -static double -sqrf(float const F) { - return F*F; -} - - - -static int -colormatch(pixel const comparand, - pixel const comparator, - float const closeness) { +static bool +colorMatches(pixel const comparand, + pixel const comparator, + unsigned int const allowableDiff) { /*---------------------------------------------------------------------------- - Return true iff 'comparand' matches 'comparator' in color within the - fuzz factor 'closeness'. + The colors 'comparand' and 'comparator' are within 'allowableDiff' + color levels of each other, in cartesian distance. -----------------------------------------------------------------------------*/ /* Fast path for usual case */ - if (closeness == 0) + if (allowableDiff < EPSILON) return PPM_EQUAL(comparand, comparator); - return PPM_DISTANCE(comparand, comparator) <= sqrf(closeness); + return PPM_DISTANCE(comparand, comparator) <= SQR(allowableDiff); } @@ -132,15 +134,18 @@ changeRow(const pixel * const inrow, const pixel colorto[], bool const remainder_specified, pixel const remainder_color, - float const closeness) { + unsigned int const allowableDiff) { /*---------------------------------------------------------------------------- Replace the colors in a single row. There are 'ncolors' colors to replace. The to-replace colors are in the array colorfrom[], and the replace-with colors are in corresponding elements of colorto[]. Iff 'remainder_specified' is true, replace all colors not mentioned - in colorfrom[] with 'remainder_color'. Use the closeness factor - 'closeness' in determining if something in the input row matches - a color in colorfrom[]. + in colorfrom[] with 'remainder_color'. + + Consider the color in inrow[] to match a color in colorfrom[] if it is + within 'allowableDiff' color levels of it, in cartesian distance (e.g. + color (1,1,1) is sqrt(12) = 3.5 color levels distant from (3,3,3), + so if 'allowableDiff' is 4, they match). The input row is 'inrow'. The output is returned as 'outrow', in storage which must be already allocated. Both are 'cols' columns wide. @@ -157,7 +162,7 @@ changeRow(const pixel * const inrow, haveMatch = FALSE; /* haven't found a match yet */ for (i = 0; i < ncolors && !haveMatch; ++i) { - haveMatch = colormatch(inrow[col], colorfrom[i], closeness); + haveMatch = colorMatches(inrow[col], colorfrom[i], allowableDiff); newcolor = colorto[i]; } if (haveMatch) @@ -172,16 +177,23 @@ changeRow(const pixel * const inrow, int -main(int argc, char *argv[]) { - struct cmdlineInfo cmdline; +main(int argc, const char ** const argv) { + + struct CmdlineInfo cmdline; FILE * ifP; int format; int rows, cols; pixval maxval; - float closeness; + unsigned int allowableDiff; + /* The amount of difference between two colors we allow and still + consider those colors to be the same, for the purposes of + determining which pixels in the image to change. This is a + cartesian distance between the color triples, on a maxval scale + (which means it can be as high as sqrt(3) * maxval) + */ int row; - pixel* inrow; - pixel* outrow; + pixel * inrow; + pixel * outrow; pixel oldcolor[TCOLS]; /* colors user wants replaced */ pixel newcolor[TCOLS]; /* colors with which he wants them replaced */ @@ -190,7 +202,7 @@ main(int argc, char *argv[]) { specify -remainder. */ - ppm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -210,8 +222,8 @@ main(int argc, char *argv[]) { cmdline.closeok); } } - closeness = SQRT3 * maxval * cmdline.closeness/100; - + allowableDiff = ROUNDU(sqrt3 * maxval * cmdline.closeness/100); + ppm_writeppminit( stdout, cols, rows, maxval, 0 ); inrow = ppm_allocrow(cols); outrow = ppm_allocrow(cols); @@ -222,7 +234,7 @@ main(int argc, char *argv[]) { changeRow(inrow, outrow, cols, cmdline.ncolors, oldcolor, newcolor, cmdline.remainder_colorname != NULL, - remainder_color, closeness); + remainder_color, allowableDiff); ppm_writeppmrow(stdout, outrow, cols, maxval, 0); } |