|
Packit |
78deda |
/******************************************************************************
|
|
Packit |
78deda |
pamsummcol
|
|
Packit |
78deda |
*******************************************************************************
|
|
Packit |
78deda |
Summarize the columns of a PAM image with various functions.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
By Bryan Henderson, San Jose CA 2004.02.07.
|
|
Packit |
78deda |
|
|
Packit |
78deda |
Contributed to the public domain
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
******************************************************************************/
|
|
Packit |
78deda |
|
|
Packit |
78deda |
#include "pm_c_util.h"
|
|
Packit |
78deda |
#include "pam.h"
|
|
Packit |
78deda |
#include "shhopt.h"
|
|
Packit |
78deda |
#include "mallocvar.h"
|
|
Packit |
78deda |
|
|
Packit |
78deda |
enum function {FN_ADD, FN_MEAN, FN_MIN, FN_MAX};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct cmdlineInfo {
|
|
Packit |
78deda |
/* All the information the user supplied in the command line,
|
|
Packit |
78deda |
in a form easy for the program to use.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
const char *inputFilespec; /* Filespec of input file */
|
|
Packit |
78deda |
enum function function;
|
|
Packit |
78deda |
unsigned int verbose;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
parseCommandLine(int argc, char ** const argv,
|
|
Packit |
78deda |
struct cmdlineInfo * const cmdlineP) {
|
|
Packit |
78deda |
/*----------------------------------------------------------------------------
|
|
Packit |
78deda |
Note that the file spec array we return is stored in the storage that
|
|
Packit |
78deda |
was passed to us as the argv array.
|
|
Packit |
78deda |
-----------------------------------------------------------------------------*/
|
|
Packit |
78deda |
optEntry *option_def = malloc(100*sizeof(optEntry));
|
|
Packit |
78deda |
/* Instructions to OptParseOptions2 on how to parse our options.
|
|
Packit |
78deda |
*/
|
|
Packit |
78deda |
optStruct3 opt;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int option_def_index;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int sumSpec, meanSpec, minSpec, maxSpec;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
option_def_index = 0; /* incremented by OPTENTRY */
|
|
Packit |
78deda |
OPTENT3(0, "sum", OPT_FLAG, NULL, &sumSpec, 0);
|
|
Packit |
78deda |
OPTENT3(0, "mean", OPT_FLAG, NULL, &meanSpec, 0);
|
|
Packit |
78deda |
OPTENT3(0, "min", OPT_FLAG, NULL, &minSpec, 0);
|
|
Packit |
78deda |
OPTENT3(0, "max", OPT_FLAG, NULL, &maxSpec, 0);
|
|
Packit |
78deda |
OPTENT3(0, "verbose", OPT_FLAG, NULL, &cmdlineP->verbose, 0);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
opt.opt_table = option_def;
|
|
Packit |
78deda |
opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */
|
|
Packit |
78deda |
opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0);
|
|
Packit |
78deda |
/* Uses and sets argc, argv, and some of *cmdlineP and others. */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (sumSpec + minSpec + maxSpec > 1)
|
|
Packit |
78deda |
pm_error("You may specify at most one of -sum, -min, and -max");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (sumSpec) {
|
|
Packit |
78deda |
cmdlineP->function = FN_ADD;
|
|
Packit |
78deda |
} else if (meanSpec) {
|
|
Packit |
78deda |
cmdlineP->function = FN_MEAN;
|
|
Packit |
78deda |
} else if (minSpec) {
|
|
Packit |
78deda |
cmdlineP->function = FN_MIN;
|
|
Packit |
78deda |
} else if (maxSpec) {
|
|
Packit |
78deda |
cmdlineP->function = FN_MAX;
|
|
Packit |
78deda |
} else
|
|
Packit |
78deda |
pm_error("You must specify one of -sum, -min, or -max");
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 > 1)
|
|
Packit |
78deda |
pm_error("Too many arguments (%d). File spec is the only argument.",
|
|
Packit |
78deda |
argc-1);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
if (argc-1 < 1)
|
|
Packit |
78deda |
cmdlineP->inputFilespec = "-";
|
|
Packit |
78deda |
else
|
|
Packit |
78deda |
cmdlineP->inputFilespec = argv[1];
|
|
Packit |
78deda |
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct accum {
|
|
Packit |
78deda |
union {
|
|
Packit |
78deda |
unsigned int sum;
|
|
Packit |
78deda |
unsigned int min;
|
|
Packit |
78deda |
unsigned int max;
|
|
Packit |
78deda |
} u;
|
|
Packit |
78deda |
};
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
createAccumulator(enum function const function,
|
|
Packit |
78deda |
unsigned int const cols,
|
|
Packit |
78deda |
unsigned int const planes,
|
|
Packit |
78deda |
struct accum *** const accumulatorP) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
struct accum ** accumulator;
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(accumulator, cols);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col) {
|
|
Packit |
78deda |
unsigned int plane;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
MALLOCARRAY_NOFAIL(accumulator[col], planes);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (plane = 0; plane < planes; ++plane) {
|
|
Packit |
78deda |
switch(function) {
|
|
Packit |
78deda |
case FN_ADD: accumulator[col][plane].u.sum = 0; break;
|
|
Packit |
78deda |
case FN_MEAN: accumulator[col][plane].u.sum = 0; break;
|
|
Packit |
78deda |
case FN_MIN: accumulator[col][plane].u.min = UINT_MAX; break;
|
|
Packit |
78deda |
case FN_MAX: accumulator[col][plane].u.max = 0; break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
*accumulatorP = accumulator;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
destroyAccumulator(struct accum ** accumulator,
|
|
Packit |
78deda |
unsigned int const cols) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
for (col = 0; col < cols; ++col)
|
|
Packit |
78deda |
free(accumulator[col]);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
free(accumulator);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
aggregate(struct pam * const inpamP,
|
|
Packit |
78deda |
tuple * const tupleRow,
|
|
Packit |
78deda |
enum function const function,
|
|
Packit |
78deda |
struct accum ** const accumulator) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < inpamP->width; ++col) {
|
|
Packit |
78deda |
unsigned int plane;
|
|
Packit |
78deda |
for (plane = 0; plane < inpamP->depth; ++plane) {
|
|
Packit |
78deda |
switch(function) {
|
|
Packit |
78deda |
case FN_ADD:
|
|
Packit |
78deda |
case FN_MEAN:
|
|
Packit |
78deda |
if (accumulator[col][plane].u.sum >
|
|
Packit |
78deda |
UINT_MAX - tupleRow[col][plane])
|
|
Packit |
78deda |
pm_error("Numerical overflow in Column %u", col);
|
|
Packit |
78deda |
accumulator[col][plane].u.sum += tupleRow[col][plane];
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FN_MIN:
|
|
Packit |
78deda |
if (tupleRow[col][plane] < accumulator[col][plane].u.min)
|
|
Packit |
78deda |
accumulator[col][plane].u.min = tupleRow[col][plane];
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FN_MAX:
|
|
Packit |
78deda |
if (tupleRow[col][plane] > accumulator[col][plane].u.min)
|
|
Packit |
78deda |
accumulator[col][plane].u.min = tupleRow[col][plane];
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
static void
|
|
Packit |
78deda |
makeSummaryRow(struct accum ** const accumulator,
|
|
Packit |
78deda |
unsigned int const count,
|
|
Packit |
78deda |
struct pam * const pamP,
|
|
Packit |
78deda |
enum function const function,
|
|
Packit |
78deda |
tuple * const tupleRow) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
unsigned int col;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (col = 0; col < pamP->width; ++col) {
|
|
Packit |
78deda |
unsigned int plane;
|
|
Packit |
78deda |
for (plane = 0; plane < pamP->depth; ++plane) {
|
|
Packit |
78deda |
switch(function) {
|
|
Packit |
78deda |
case FN_ADD:
|
|
Packit |
78deda |
tupleRow[col][plane] =
|
|
Packit |
78deda |
MIN(accumulator[col][plane].u.sum, pamP->maxval);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FN_MEAN:
|
|
Packit |
78deda |
tupleRow[col][plane] =
|
|
Packit |
78deda |
ROUNDU((double)accumulator[col][plane].u.sum / count);
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FN_MIN:
|
|
Packit |
78deda |
tupleRow[col][plane] =
|
|
Packit |
78deda |
accumulator[col][plane].u.min;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
case FN_MAX:
|
|
Packit |
78deda |
tupleRow[col][plane] =
|
|
Packit |
78deda |
accumulator[col][plane].u.max;
|
|
Packit |
78deda |
break;
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
|
|
Packit |
78deda |
int
|
|
Packit |
78deda |
main(int argc, char *argv[]) {
|
|
Packit |
78deda |
|
|
Packit |
78deda |
FILE* ifP;
|
|
Packit |
78deda |
tuple* inputRow; /* Row from input image */
|
|
Packit |
78deda |
tuple* outputRow; /* Output row */
|
|
Packit |
78deda |
int row;
|
|
Packit |
78deda |
struct cmdlineInfo cmdline;
|
|
Packit |
78deda |
struct pam inpam; /* Input PAM image */
|
|
Packit |
78deda |
struct pam outpam; /* Output PAM image */
|
|
Packit |
78deda |
struct accum ** accumulator; /* malloc'ed two-dimensional array */
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_init( &argc, argv );
|
|
Packit |
78deda |
|
|
Packit |
78deda |
parseCommandLine(argc, argv, &cmdline);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
ifP = pm_openr(cmdline.inputFilespec);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_readpaminit(ifP, &inpam, PAM_STRUCT_SIZE(tuple_type));
|
|
Packit |
78deda |
|
|
Packit |
78deda |
createAccumulator(cmdline.function, inpam.width, inpam.depth,
|
|
Packit |
78deda |
&accumulator);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
inputRow = pnm_allocpamrow(&inpam);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
outpam = inpam; /* Initial value -- most fields should be same */
|
|
Packit |
78deda |
outpam.file = stdout;
|
|
Packit |
78deda |
outpam.height = 1;
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_writepaminit(&outpam);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
outputRow = pnm_allocpamrow(&outpam);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
for (row = 0; row < inpam.height; row++) {
|
|
Packit |
78deda |
pnm_readpamrow(&inpam, inputRow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
aggregate(&inpam, inputRow, cmdline.function, accumulator);
|
|
Packit |
78deda |
}
|
|
Packit |
78deda |
makeSummaryRow(accumulator, inpam.height, &outpam, cmdline.function,
|
|
Packit |
78deda |
outputRow);
|
|
Packit |
78deda |
pnm_writepamrow(&outpam, outputRow);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
pnm_freepamrow(outputRow);
|
|
Packit |
78deda |
pnm_freepamrow(inputRow);
|
|
Packit |
78deda |
destroyAccumulator(accumulator, inpam.width);
|
|
Packit |
78deda |
pm_close(inpam.file);
|
|
Packit |
78deda |
pm_close(outpam.file);
|
|
Packit |
78deda |
|
|
Packit |
78deda |
return 0;
|
|
Packit |
78deda |
}
|