diff options
Diffstat (limited to 'editor/pamfunc.c')
-rw-r--r-- | editor/pamfunc.c | 190 |
1 files changed, 172 insertions, 18 deletions
diff --git a/editor/pamfunc.c b/editor/pamfunc.c index dbb1ca70..d380303a 100644 --- a/editor/pamfunc.c +++ b/editor/pamfunc.c @@ -18,10 +18,24 @@ ******************************************************************************/ -#include "pam.h" +#include "mallocvar.h" #include "shhopt.h" +#include "pam.h" -enum function {FN_MULTIPLY, FN_DIVIDE, FN_ADD, FN_SUBTRACT, FN_MIN, FN_MAX}; +enum function { + FN_MULTIPLY, + FN_DIVIDE, + FN_ADD, + FN_SUBTRACT, + FN_MIN, + FN_MAX, + FN_AND, + FN_OR, + FN_XOR, + FN_NOT, + FN_SHIFTLEFT, + FN_SHIFTRIGHT +}; /* Note that when the user specifies a minimum, that means he's requesting a "max" function. @@ -40,11 +54,30 @@ struct cmdlineInfo { int subtractor; unsigned int max; unsigned int min; + unsigned int mask; + unsigned int shiftCount; } u; unsigned int verbose; }; + +static unsigned int +parseHex(const char * const hexString) { + + unsigned int retval; + char * tail; + + retval = strtol(hexString, &tail, 16); + + if (*tail != '\0') + pm_error("Invalid hex string '%s'. Junk: '%s'", hexString, tail); + + return retval; +} + + + static void parseCommandLine(int argc, char ** const argv, struct cmdlineInfo * const cmdlineP) { @@ -52,29 +85,46 @@ parseCommandLine(int argc, char ** const argv, 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 = malloc(100*sizeof(optEntry)); - /* Instructions to OptParseOptions2 on how to parse our options. - */ + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options. */ optStruct3 opt; unsigned int option_def_index; unsigned int multiplierSpec, divisorSpec, adderSpec, subtractorSpec; unsigned int maxSpec, minSpec; + unsigned int andmaskSpec, ormaskSpec, xormaskSpec, notSpec; + unsigned int shiftleftSpec, shiftrightSpec; + + const char * mask; + + MALLOCARRAY(option_def, 100); - option_def_index = 0; /* incremented by OPTENTRY */ + option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "multiplier", OPT_FLOAT, &cmdlineP->u.multiplier, &multiplierSpec, 0); OPTENT3(0, "divisor", OPT_FLOAT, &cmdlineP->u.divisor, - &divisorSpec, 0); + &divisorSpec, 0); OPTENT3(0, "adder", OPT_INT, &cmdlineP->u.adder, - &adderSpec, 0); + &adderSpec, 0); OPTENT3(0, "subtractor", OPT_INT, &cmdlineP->u.subtractor, &subtractorSpec, 0); OPTENT3(0, "min", OPT_UINT, &cmdlineP->u.min, - &minSpec, 0); + &minSpec, 0); OPTENT3(0, "max", OPT_UINT, &cmdlineP->u.max, - &maxSpec, 0); + &maxSpec, 0); + OPTENT3(0, "andmask", OPT_STRING, &mask, + &andmaskSpec, 0); + OPTENT3(0, "ormask", OPT_STRING, &mask, + &ormaskSpec, 0); + OPTENT3(0, "xormask", OPT_STRING, &mask, + &xormaskSpec, 0); + OPTENT3(0, "not", OPT_FLAG, NULL, + ¬Spec, 0); + OPTENT3(0, "shiftleft", OPT_UINT, &cmdlineP->u.shiftCount, + &shiftleftSpec, 0); + OPTENT3(0, "shiftright", OPT_UINT, &cmdlineP->u.shiftCount, + &shiftrightSpec, 0); OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0); opt.opt_table = option_def; @@ -85,9 +135,12 @@ parseCommandLine(int argc, char ** const argv, /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (multiplierSpec + divisorSpec + adderSpec + subtractorSpec + - minSpec + maxSpec > 1) + minSpec + maxSpec + andmaskSpec + ormaskSpec + xormaskSpec + notSpec + + shiftleftSpec + shiftrightSpec > 1) pm_error("You may specify at most one of -multiplier, -divisor," - "-adder, -subtractor, -min, and -max"); + "-adder, -subtractor, -min, -max, " + "-andmask, -ormask, -xormask, -not, " + "-shiftleft, and -shiftright"); if (multiplierSpec) { cmdlineP->function = FN_MULTIPLY; @@ -107,9 +160,25 @@ parseCommandLine(int argc, char ** const argv, cmdlineP->function = FN_MAX; } else if (maxSpec) { cmdlineP->function = FN_MIN; + } else if (andmaskSpec) { + cmdlineP->function = FN_AND; + cmdlineP->u.mask = parseHex(mask); + } else if (ormaskSpec) { + cmdlineP->function = FN_OR; + cmdlineP->u.mask = parseHex(mask); + } else if (xormaskSpec) { + cmdlineP->function = FN_XOR; + cmdlineP->u.mask = parseHex(mask); + } else if (notSpec) { + cmdlineP->function = FN_NOT; + } else if (shiftleftSpec) { + cmdlineP->function = FN_SHIFTLEFT; + } else if (shiftrightSpec) { + cmdlineP->function = FN_SHIFTRIGHT; } else pm_error("You must specify one of -multiplier, -divisor, " - "-adder, -subtractor, -min, or -max"); + "-adder, -subtractor, -min, -max, " + "-and, -or, -xor, -not, -shiftleft, or -shiftright"); if (argc-1 > 1) pm_error("Too many arguments (%d). File spec is the only argument.", @@ -124,6 +193,70 @@ parseCommandLine(int argc, char ** const argv, +static bool +isDyadicMaskFunction(enum function const fn) { + + return (fn == FN_AND || fn == FN_OR || fn == FN_XOR); +} + + + +static bool +isMaskFunction(enum function const fn) { + + return (isDyadicMaskFunction(fn) || fn == FN_NOT); +} + + + +static bool +isShiftFunction(enum function const fn) { + + return (fn == FN_SHIFTLEFT || fn == FN_SHIFTRIGHT); +} + + + +static bool +isBitstringFunction(enum function const fn) { + + return isMaskFunction(fn) || isShiftFunction(fn); +} + + + +static void +validateFunction(struct cmdlineInfo const cmdline, + const struct pam * const pamP) { + + if (isBitstringFunction(cmdline.function)) { + if (pm_bitstomaxval(pm_maxvaltobits(pamP->maxval)) != pamP->maxval) + pm_error("For a bit string function, the maxval must be a full " + "binary count, i.e. a power of two minus one such as " + "0xff or 0x1. You have 0x%x", + (unsigned)pamP->maxval); + + if (isDyadicMaskFunction(cmdline.function)) { + if ((cmdline.u.mask & pamP->maxval) != cmdline.u.mask) + pm_error("Your bit string mask 0x%x is wider than the samples " + "of the image (%u bits, according to the maxval %lu", + cmdline.u.mask, pm_maxvaltobits(pamP->maxval), + pamP->maxval); + } + + if (isShiftFunction(cmdline.function)) { + if (cmdline.u.shiftCount > pm_maxvaltobits(pamP->maxval)) + pm_error("Your shift count (%u) is greater than the width " + "of the samples of the image (%u bits, according " + "to the maxval %lu)", + cmdline.u.shiftCount, pm_maxvaltobits(pamP->maxval), + pamP->maxval); + } + } +} + + + static void applyFunction(struct cmdlineInfo const cmdline, struct pam const inpam, @@ -168,6 +301,25 @@ applyFunction(struct cmdlineInfo const cmdline, case FN_MIN: outSample = MIN(inSample, cmdline.u.max); break; + case FN_AND: + outSample = inSample & cmdline.u.mask; + break; + case FN_OR: + outSample = inSample | cmdline.u.mask; + break; + case FN_XOR: + outSample = inSample ^ cmdline.u.mask; + break; + case FN_NOT: + outSample = ~inSample; + break; + case FN_SHIFTLEFT: + outSample = + (inSample << cmdline.u.shiftCount) & outpam.maxval; + break; + case FN_SHIFTRIGHT: + outSample = inSample >> cmdline.u.shiftCount; + break; } outputRow[col][plane] = MIN(outpam.maxval, outSample); } @@ -179,15 +331,15 @@ applyFunction(struct cmdlineInfo const cmdline, int main(int argc, char *argv[]) { - FILE* ifP; - tuple* inputRow; /* Row from input image */ - tuple* outputRow; /* Row of output image */ + FILE * ifP; + tuple * inputRow; /* Row from input image */ + tuple * outputRow; /* Row of output image */ int row; struct cmdlineInfo cmdline; struct pam inpam; /* Input PAM image */ struct pam outpam; /* Output PAM image */ - pnm_init( &argc, argv ); + pnm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -195,6 +347,8 @@ main(int argc, char *argv[]) { pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type)); + validateFunction(cmdline, &inpam); + inputRow = pnm_allocpamrow(&inpam); outpam = inpam; /* Initial value -- most fields should be same */ @@ -216,6 +370,6 @@ main(int argc, char *argv[]) { pm_close(inpam.file); pm_close(outpam.file); - exit(0); + return 0; } |