diff options
Diffstat (limited to 'converter/other/pgmtopbm.c')
-rw-r--r-- | converter/other/pgmtopbm.c | 114 |
1 files changed, 65 insertions, 49 deletions
diff --git a/converter/other/pgmtopbm.c b/converter/other/pgmtopbm.c index 67cac468..64dc814b 100644 --- a/converter/other/pgmtopbm.c +++ b/converter/other/pgmtopbm.c @@ -21,15 +21,18 @@ enum halftone {QT_FS, QT_THRESH, QT_DITHER8, QT_CLUSTER, QT_HILBERT}; -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; enum halftone halftone; unsigned int clumpSize; - unsigned int clusterRadius; + unsigned int clusterRadius; /* Defined only for halftone == QT_CLUSTER */ + unsigned int randomSeed; + unsigned int randomSeedSpec; + /* Defined only for halftone == QT_FS */ float threshval; }; @@ -37,8 +40,8 @@ struct cmdlineInfo { static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo *cmdlineP) { +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo *cmdlineP) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. @@ -68,22 +71,24 @@ parseCommandLine(int argc, char ** argv, OPTENT3(0, "c4", OPT_FLAG, NULL, &cluster4Opt, 0); OPTENT3(0, "cluster8", OPT_FLAG, NULL, &cluster8Opt, 0); OPTENT3(0, "c8", OPT_FLAG, NULL, &cluster8Opt, 0); - OPTENT3(0, "value", OPT_FLOAT, &cmdlineP->threshval, + OPTENT3(0, "value", OPT_FLOAT, &cmdlineP->threshval, &valueSpec, 0); - OPTENT3(0, "clump", OPT_UINT, &cmdlineP->clumpSize, + OPTENT3(0, "clump", OPT_UINT, &cmdlineP->clumpSize, &clumpSpec, 0); + OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomSeed, + &cmdlineP->randomSeedSpec, 0); opt.opt_table = option_def; 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 (floydOpt + thresholdOpt + hilbertOpt + dither8Opt + + if (floydOpt + thresholdOpt + hilbertOpt + dither8Opt + cluster3Opt + cluster4Opt + cluster8Opt == 0) cmdlineP->halftone = QT_FS; - else if (floydOpt + thresholdOpt + dither8Opt + + else if (floydOpt + thresholdOpt + dither8Opt + cluster3Opt + cluster4Opt + cluster8Opt > 1) pm_error("No cannot specify more than one halftoning type"); else { @@ -104,7 +109,7 @@ parseCommandLine(int argc, char ** argv, } else if (cluster8Opt) { cmdlineP->halftone = QT_CLUSTER; cmdlineP->clusterRadius = 8; - } else + } else pm_error("INTERNAL ERROR. No halftone option"); } @@ -118,7 +123,7 @@ parseCommandLine(int argc, char ** argv, pm_error("-value cannot be greater than one. You specified %f", cmdlineP->threshval); } - + if (!clumpSpec) cmdlineP->clumpSize = 5; else { @@ -127,6 +132,10 @@ parseCommandLine(int argc, char ** argv, cmdlineP->clumpSize); } + if (cmdlineP->halftone != QT_FS && cmdlineP->randomSeedSpec) + pm_message ("Ignoring -randomseed value " + "(meaningful only with Floyd-Steinberg)"); + if (argc-1 > 1) pm_error("Too many arguments (%d). There is at most one " "non-option argument: the file name", @@ -150,11 +159,11 @@ static int hil_x,hil_y; static int hil_stage[MAXORD]; static int hil_width,hil_height; -static void -init_hilbert(int const w, +static void +init_hilbert(int const w, int const h) { /*---------------------------------------------------------------------------- - Initialize the Hilbert curve tracer + Initialize the Hilbert curve tracer -----------------------------------------------------------------------------*/ int big,ber; hil_width = w; @@ -169,7 +178,7 @@ init_hilbert(int const w, -static int +static int hilbert(int * const px, int * const py) { /*---------------------------------------------------------------------------- Return non-zero if got another point @@ -215,7 +224,7 @@ hilbert(int * const px, int * const py) { temp = hil_dy; hil_dy = -hil_turn * hil_dx; hil_dx = hil_turn * temp; - if (hil_ord > 0) { + if (hil_ord > 0) { /* recurse */ hil_stage[hil_ord] = 3; @@ -338,7 +347,7 @@ static void doHilbert(FILE * const ifP, struct converter { void (*convertRow)(struct converter * const converterP, unsigned int const row, - gray grayrow[], + gray grayrow[], bit bitrow[]); void (*destroy)(struct converter * const converterP); unsigned int cols; @@ -379,7 +388,7 @@ fsConvertRow(struct converter * const converterP, unsigned int limitcol; unsigned int col; - + for (col = 0; col < converterP->cols + 2; ++col) nexterr[col] = 0; if (stateP->fs_forward) { @@ -395,20 +404,20 @@ fsConvertRow(struct converter * const converterP, } do { long sum; - sum = ((long) *gP * fs_scale) / converterP->maxval + + sum = ((long) *gP * fs_scale) / converterP->maxval + thiserr[col + 1]; if (sum >= stateP->threshval) { *bP = PBM_WHITE; sum = sum - stateP->threshval - half_fs_scale; } else *bP = PBM_BLACK; - + if (stateP->fs_forward) { thiserr[col + 2] += (sum * 7) / 16; nexterr[col ] += (sum * 3) / 16; nexterr[col + 1] += (sum * 5) / 16; nexterr[col + 2] += (sum ) / 16; - + ++col; ++gP; ++bP; @@ -417,13 +426,13 @@ fsConvertRow(struct converter * const converterP, nexterr[col + 2] += (sum * 3) / 16; nexterr[col + 1] += (sum * 5) / 16; nexterr[col ] += (sum ) / 16; - + --col; --gP; --bP; } } while (col != limitcol); - + stateP->thiserr = nexterr; stateP->nexterr = thiserr; stateP->fs_forward = ! stateP->fs_forward; @@ -439,9 +448,11 @@ fsDestroy(struct converter * const converterP) { static struct converter -createFsConverter(unsigned int const cols, +createFsConverter(unsigned int const cols, gray const maxval, - float const threshFraction) { + float const threshFraction, + unsigned int const randomSeedSpec, + unsigned int const randomSeed) { struct fsState * stateP; struct converter converter; @@ -451,13 +462,13 @@ createFsConverter(unsigned int const cols, /* Initialize Floyd-Steinberg error vectors. */ MALLOCARRAY_NOFAIL(stateP->thiserr, cols + 2); MALLOCARRAY_NOFAIL(stateP->nexterr, cols + 2); - srand(pm_randseed()); + srand(randomSeedSpec ? randomSeed : pm_randseed()); { /* (random errors in [-fs_scale/8 .. fs_scale/8]) */ unsigned int col; for (col = 0; col < cols + 2; ++col) - stateP->thiserr[col] = + stateP->thiserr[col] = (long)(rand() % fs_scale - half_fs_scale) / 4; } @@ -488,7 +499,7 @@ threshConvertRow(struct converter * const converterP, unsigned int const row, gray grayrow[], bit bitrow[]) { - + struct threshState * const stateP = converterP->stateP; unsigned int col; @@ -509,7 +520,7 @@ threshDestroy(struct converter * const converterP) { static struct converter -createThreshConverter(unsigned int const cols, +createThreshConverter(unsigned int const cols, gray const maxval, float const threshFraction) { @@ -571,7 +582,7 @@ dither8Destroy(struct converter * const converterP) { static struct converter -createDither8Converter(unsigned int const cols, +createDither8Converter(unsigned int const cols, gray const maxval) { struct converter converter; @@ -642,7 +653,7 @@ clusterDestroy(struct converter * const converterP) { free(stateP->clusterMatrix[row]); free(stateP->clusterMatrix); - + free(stateP); } @@ -650,9 +661,9 @@ clusterDestroy(struct converter * const converterP) { static struct converter createClusterConverter(unsigned int const radius, - unsigned int const cols, + unsigned int const cols, gray const maxval) { - + int const clusterNormalizer = radius * radius * 2; unsigned int const diameter = 2 * radius; @@ -674,7 +685,7 @@ createClusterConverter(unsigned int const radius, unsigned int col; MALLOCARRAY_NOFAIL(stateP->clusterMatrix[row], diameter); - + for (col = 0; col < diameter; ++col) { int val; switch (radius) { @@ -686,7 +697,7 @@ createClusterConverter(unsigned int const radius, } stateP->clusterMatrix[row][col] = val * maxval / clusterNormalizer; } - } + } converter.stateP = stateP; @@ -696,14 +707,14 @@ createClusterConverter(unsigned int const radius, int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { - struct cmdlineInfo cmdline; - FILE* ifP; - gray* grayrow; - bit* bitrow; + struct CmdlineInfo cmdline; + FILE * ifP; + gray * grayrow; + bit * bitrow; - pgm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); @@ -719,24 +730,26 @@ main(int argc, char *argv[]) { int row; pgm_readpgminit(ifP, &cols, &rows, &maxval, &format); - + pbm_writepbminit(stdout, cols, rows, 0); switch (cmdline.halftone) { case QT_FS: - converter = createFsConverter(cols, maxval, cmdline.threshval); + converter = createFsConverter(cols, maxval, cmdline.threshval, + cmdline.randomSeedSpec, + cmdline.randomSeed); break; case QT_THRESH: converter = createThreshConverter(cols, maxval, cmdline.threshval); break; - case QT_DITHER8: - converter = createDither8Converter(cols, maxval); + case QT_DITHER8: + converter = createDither8Converter(cols, maxval); break; - case QT_CLUSTER: - converter = + case QT_CLUSTER: + converter = createClusterConverter(cmdline.clusterRadius, cols, maxval); break; - case QT_HILBERT: + case QT_HILBERT: pm_error("INTERNAL ERROR: halftone is QT_HILBERT where it " "shouldn't be."); break; @@ -749,7 +762,7 @@ main(int argc, char *argv[]) { pgm_readpgmrow(ifP, grayrow, cols, maxval, format); converter.convertRow(&converter, row, grayrow, bitrow); - + pbm_writepbmrow(stdout, bitrow, cols, 0); } pbm_freerow(bitrow); @@ -763,3 +776,6 @@ main(int argc, char *argv[]) { return 0; } + + + |