diff options
Diffstat (limited to 'editor/pamfunc.c')
-rw-r--r-- | editor/pamfunc.c | 128 |
1 files changed, 96 insertions, 32 deletions
diff --git a/editor/pamfunc.c b/editor/pamfunc.c index b6e56e17..5945b82d 100644 --- a/editor/pamfunc.c +++ b/editor/pamfunc.c @@ -13,8 +13,8 @@ multiply/divide where possible. Especially when multiplying by an integer. - 2) For multiply/divide, give option of simply changing the maxval and - leaving the raster alone. + 2) speed up by not transforming the raster in the idempotent cases + (e.g. multiply by one). ******************************************************************************/ @@ -23,7 +23,7 @@ #include "shhopt.h" #include "pam.h" -enum function { +enum Function { FN_MULTIPLY, FN_DIVIDE, FN_ADD, @@ -42,22 +42,23 @@ enum function { a "max" function. */ -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 *inputFilespec; /* Filespec of input file */ - enum function function; + const char * inputFileName; + enum Function function; union { - float multiplier; - float divisor; - int adder; - int subtractor; + float multiplier; + float divisor; + int adder; + int subtractor; unsigned int max; unsigned int min; unsigned int mask; unsigned int shiftCount; } u; + unsigned int changemaxval; unsigned int verbose; }; @@ -80,8 +81,8 @@ parseHex(const char * const hexString) { static void -parseCommandLine(int argc, char ** const 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. @@ -126,13 +127,16 @@ parseCommandLine(int argc, char ** const argv, &shiftleftSpec, 0); OPTENT3(0, "shiftright", OPT_UINT, &cmdlineP->u.shiftCount, &shiftrightSpec, 0); - OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); + OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, + 0); + OPTENT3(0, "changemaxval", OPT_FLAG, NULL, &cmdlineP->changemaxval, + 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no 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 (multiplierSpec + divisorSpec + adderSpec + subtractorSpec + @@ -186,16 +190,17 @@ parseCommandLine(int argc, char ** const argv, argc-1); if (argc-1 < 1) - cmdlineP->inputFilespec = "-"; + cmdlineP->inputFileName = "-"; else - cmdlineP->inputFilespec = argv[1]; + cmdlineP->inputFileName = argv[1]; + free(option_def); } static bool -isDyadicMaskFunction(enum function const fn) { +isDyadicMaskFunction(enum Function const fn) { return (fn == FN_AND || fn == FN_OR || fn == FN_XOR); } @@ -203,7 +208,7 @@ isDyadicMaskFunction(enum function const fn) { static bool -isMaskFunction(enum function const fn) { +isMaskFunction(enum Function const fn) { return (isDyadicMaskFunction(fn) || fn == FN_NOT); } @@ -211,7 +216,7 @@ isMaskFunction(enum function const fn) { static bool -isShiftFunction(enum function const fn) { +isShiftFunction(enum Function const fn) { return (fn == FN_SHIFTLEFT || fn == FN_SHIFTRIGHT); } @@ -219,7 +224,7 @@ isShiftFunction(enum function const fn) { static bool -isBitstringFunction(enum function const fn) { +isBitstringFunction(enum Function const fn) { return isMaskFunction(fn) || isShiftFunction(fn); } @@ -227,7 +232,7 @@ isBitstringFunction(enum function const fn) { static void -validateFunction(struct cmdlineInfo const cmdline, +validateFunction(struct CmdlineInfo const cmdline, const struct pam * const pamP) { if (isBitstringFunction(cmdline.function)) { @@ -259,7 +264,58 @@ validateFunction(struct cmdlineInfo const cmdline, static void -applyFunction(struct cmdlineInfo const cmdline, +planTransform(struct CmdlineInfo const cmdline, + sample const inputMaxval, + sample * const outputMaxvalP, + bool * const mustChangeRasterP) { +/*---------------------------------------------------------------------------- + Plan the transform described by 'cmdline', given the maxval of the input + image is 'inputMaxval. + + The plan just consists of whether to change the maxval or the raster. + Some multiplications and divisions can be achieved just by changing the + maxval and leaving the samples in the raster alone. +-----------------------------------------------------------------------------*/ + if (cmdline.changemaxval) { + /* User allows us to change the maxval, if that makes it easier */ + if (cmdline.function == FN_MULTIPLY || cmdline.function == FN_DIVIDE) { + float const multiplier = + cmdline.function == FN_MULTIPLY ? cmdline.u.multiplier : + (1/cmdline.u.divisor); + + float const neededMaxval = inputMaxval / multiplier; + + if (neededMaxval + 0.5 < inputMaxval) { + /* Lowering the maxval might make some of the sample values + higher than the maxval, so we'd have to modify the raster + to clip them. + */ + *outputMaxvalP = inputMaxval; + *mustChangeRasterP = true; + } else if (neededMaxval > PAM_OVERALL_MAXVAL) { + *outputMaxvalP = inputMaxval; + *mustChangeRasterP = true; + } else { + *outputMaxvalP = ROUNDU(neededMaxval); + *mustChangeRasterP = false; + } + } else { + *outputMaxvalP = inputMaxval; + *mustChangeRasterP = true; + } + } else { + *outputMaxvalP = inputMaxval; + *mustChangeRasterP = true; + } + if (*outputMaxvalP != inputMaxval) + pm_message("Changing maxval to %u because of -changemaxval", + (unsigned)*outputMaxvalP); +} + + + +static void +applyFunction(struct CmdlineInfo const cmdline, struct pam const inpam, struct pam const outpam, tuple * const inputRow, @@ -275,10 +331,10 @@ applyFunction(struct cmdlineInfo const cmdline, divide, both cmdline.u.divisor and oneOverDivisor are meaningless. */ - int col; + unsigned int col; for (col = 0; col < inpam.width; ++col) { - int plane; + unsigned int plane; for (plane = 0; plane < inpam.depth; ++plane) { sample const inSample = inputRow[col][plane]; sample outSample; /* Could be > maxval */ @@ -330,21 +386,22 @@ applyFunction(struct cmdlineInfo const cmdline, int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { FILE * ifP; tuple * inputRow; /* Row from input image */ tuple * outputRow; /* Row of output image */ - int row; - struct cmdlineInfo cmdline; + unsigned int row; + struct CmdlineInfo cmdline; struct pam inpam; /* Input PAM image */ struct pam outpam; /* Output PAM image */ + bool mustChangeRaster; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); - ifP = pm_openr(cmdline.inputFilespec); + ifP = pm_openr(cmdline.inputFileName); pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); @@ -355,16 +412,21 @@ main(int argc, char *argv[]) { outpam = inpam; /* Initial value -- most fields should be same */ outpam.file = stdout; + planTransform(cmdline, inpam.maxval, &outpam.maxval, &mustChangeRaster); + pnm_writepaminit(&outpam); outputRow = pnm_allocpamrow(&outpam); - for (row = 0; row < inpam.height; row++) { + for (row = 0; row < inpam.height; ++row) { pnm_readpamrow(&inpam, inputRow); - applyFunction(cmdline, inpam, outpam, inputRow, outputRow); + if (mustChangeRaster) { + applyFunction(cmdline, inpam, outpam, inputRow, outputRow); - pnm_writepamrow(&outpam, outputRow); + pnm_writepamrow(&outpam, outputRow); + } else + pnm_writepamrow(&outpam, inputRow); } pnm_freepamrow(outputRow); pnm_freepamrow(inputRow); @@ -374,3 +436,5 @@ main(int argc, char *argv[]) { return 0; } + + |