diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-12-27 17:33:56 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2021-12-27 17:33:56 +0000 |
commit | 6e629f983aa205c3eaa5f339f1c71bb5e7938049 (patch) | |
tree | a89f594443ac2330138f0bd0f19ee59135c2213f /generator | |
parent | ec52f41aabc9de9aac203c2f462252e403c7374a (diff) | |
download | netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.tar.gz netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.tar.xz netpbm-mirror-6e629f983aa205c3eaa5f339f1c71bb5e7938049.zip |
Promote Development to Advanced to make Release 10.97.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@4222 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator')
-rw-r--r-- | generator/Makefile | 2 | ||||
-rw-r--r-- | generator/pbmnoise.c | 484 | ||||
-rw-r--r-- | generator/pbmtext.c | 2 | ||||
-rw-r--r-- | generator/ppmmake.c | 4 | ||||
-rw-r--r-- | generator/ppmpat.c | 202 |
5 files changed, 614 insertions, 80 deletions
diff --git a/generator/Makefile b/generator/Makefile index d54a6cc5..761181bd 100644 --- a/generator/Makefile +++ b/generator/Makefile @@ -18,7 +18,7 @@ SUBDIRS = pamtris PORTBINARIES = pamcrater pamgauss pamgradient \ pamseq pamshadedrelief pamstereogram \ - pbmpage pbmmake pbmtext pbmupc \ + pbmpage pbmmake pbmnoise pbmtext pbmupc \ pgmkernel pgmmake pgmnoise pgmramp \ ppmcie ppmcolors ppmforge ppmmake ppmpat ppmrough ppmwheel \ diff --git a/generator/pbmnoise.c b/generator/pbmnoise.c new file mode 100644 index 00000000..9a537d5c --- /dev/null +++ b/generator/pbmnoise.c @@ -0,0 +1,484 @@ +/* pbmnoise.c - create a random bitmap of a specified size + with a specified ratio of white/black pixels + + Written by Akira F Urushibata and contributed to the public domain + December 2021 +*/ + +#include <math.h> +#include <string.h> +#include <assert.h> + +#include "pm_c_util.h" +#include "shhopt.h" +#include "mallocvar.h" +#include "rand.h" +#include "nstring.h" + +#include "pbm.h" + + + +static void +parseFraction(const char * const fraction, + unsigned int * const numeratorP, + unsigned int * const precisionP) { + + unsigned int numerator, denominator; + + sscanf(fraction, "%u/%u", &numerator, &denominator); + + if (denominator > 65536) + pm_error("Denominator (%u) too large.", denominator); + else if (denominator == 0 || (denominator & (denominator - 1)) != 0) + pm_error("Denominator must be a power of two. You specified %u.", + denominator); + else if (numerator > denominator) + pm_error("Invalid fraction (%s). Denominator must be larger than " + "numerator.", fraction); + else { + /* Reduce fraction to lowest terms */ + unsigned int numerator2, denominator2; + /* The fraction reduced to lowest terms */ + unsigned int precision2; + + if (numerator == 0) { /* all white image */ + numerator2 = 0; + denominator2 = 1; + precision2 = 0; + } else if (numerator == denominator) { /* all black */ + numerator2 = 1; + denominator2 = 1; + precision2 = 0; + } else { + numerator2 = numerator; /* initial value */ + denominator2 = denominator; /* initial value */ + + while ((numerator2 & 0x01) != 0x01) { + denominator2 /= 2; + numerator2 /= 2; + } + precision2 = 1; + } + + if (denominator != denominator2) + pm_message("Ratio %u/%u = %u/%u", + numerator, denominator, numerator2, denominator2); + + *precisionP = (precision2 == 0) ? 0 : pm_maxvaltobits(denominator2 - 1); + /* pm_maxvaltobits(N): Max of N is 65535 */ + + *numeratorP = numerator2; + } +} + + + +static void +setRatio(const char * const ratioArg, + unsigned int * const numeratorP, + unsigned int * const precisionP) { +/*---------------------------------------------------------------------------- + Convert string "ratioArg" to ratio: numerator / (2 ^ precision) The input + string must be in fraction "n/d" form and the denominator must be a power + of 2. + + Ratio is the probability of one binary digit being "1". The ratio of "1" + (=PBM black) pixels in the entire output image will be close to this + value. + + Most invalid strings are rejected here. +----------------------------------------------------------------------------*/ + if (strspn(ratioArg, "0123456789/") == strlen(ratioArg) && + ratioArg[0] != '/' && + ratioArg[strlen(ratioArg) - 1] != '/' && + strchr(ratioArg, '/') != NULL && + strchr(ratioArg, '/') == strrchr(ratioArg, '/')) + parseFraction(ratioArg, numeratorP, precisionP); + else + pm_error("Invalid ratio: '%s'", ratioArg); +} + + + +struct CmdlineInfo { + /* All the information the user supplied in the command line, + in a form easy for the program to use. + */ + unsigned int width; + unsigned int height; + unsigned int numerator; + unsigned int precision; + unsigned int randomseed; + unsigned int randomseedSpec; + unsigned int bswap; /* boolean */ + unsigned int pack; /* boolean */ +}; + + + +static void +parseCommandLine(int argc, const char ** 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. +-----------------------------------------------------------------------------*/ + optEntry *option_def; + /* Instructions to pm_optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + const char * ratioArg; + unsigned int ratioSpec; + const char * endianArg; + unsigned int endianSpec; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "ratio", OPT_STRING, &ratioArg, + &ratioSpec, 0); + OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomseed, + &cmdlineP->randomseedSpec, 0); + OPTENT3(0, "endian", OPT_STRING, &endianArg, + &endianSpec, 0); + OPTENT3(0, "pack", OPT_FLAG, NULL, + &cmdlineP->pack, 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, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + free(option_def); + + if (ratioSpec) + setRatio(ratioArg, &cmdlineP->numerator, &cmdlineP->precision); + else { + /* Set ratio to default: 1/2 */ + cmdlineP->numerator = 1; + cmdlineP->precision = 1; + } + + if (!endianSpec) + cmdlineP->bswap = false; + else { + if (streq(endianArg, "native")) + cmdlineP->bswap = false; + else if (streq(endianArg, "swap")) + cmdlineP->bswap = true; + else if (streq(endianArg, "big")) + cmdlineP->bswap = (BYTE_ORDER == LITTLE_ENDIAN); + else if (streq(endianArg, "little")) + cmdlineP->bswap = (BYTE_ORDER != LITTLE_ENDIAN); + else + pm_error("Invalid value '%s' for -endian argument.", endianArg); + } + + if (argc-1 != 2) + pm_error("Wrong number of arguments (%d). There are two " + "non-option arguments: width and height in pixels", + argc-1); + else { + cmdlineP->width = pm_parse_width (argv[1]); + cmdlineP->height = pm_parse_height(argv[2]); + } +} + + + +static void +writeSingleColorRaster(unsigned int const cols, + unsigned int const rows, + bit const color, + FILE * const ofP) { +/*----------------------------------------------------------------------------- + Generate a single-color raster of color 'color', dimensions + 'cols' by 'rows', to output file *ofP. +-----------------------------------------------------------------------------*/ + unsigned int const lastColChar = (cols - 1) / 8; + + unsigned char * bitrow0; + unsigned int i; + + bitrow0 = pbm_allocrow_packed(cols + 32); + + for (i = 0; i <= lastColChar; ++i) + bitrow0[i] = color * 0xff; + + if (color != 0) + pbm_cleanrowend_packed(bitrow0, cols); + + /* row end trimming, not necessary with white */ + + { + unsigned int row; + for (row = 0; row < rows; ++row) + pbm_writepbmrow_packed(ofP, bitrow0, cols, 0); + } + pbm_freerow(bitrow0); +} + + + +static uint32_t +randombits(unsigned int const precision, + unsigned int const numerator, + struct pm_randSt * const randStP) { +/*---------------------------------------------------------------------------- + Generate 32 random bits so that for each bit the probability of "1" + being generated is numerator / (2 ^ precision). + + How this works: + + Ratios such as 1/8, 7/8, 1/16, 15/16, 1/32, 31/32 are straightforward. How + do you get intermediate values such as 3/8, 5/8, 3/16, 5/16, 7/16? + + Imagine a set of 10 bits which are 90% 1, 10% 0 and a random number source + which produces 1 and 0 in even proportions. + + Conduct "and" and "or" on these bits: + + 0011111111 (90%) 0011111111 (90%) + and) 0101010101 (50%) or) 0101010101 (50%) + --------------------- -------------------- + 0001010101 (45%) 0111111111 (95%) + + It can be seen from this example that an "and" operation gives a new ratio + which is halfway between the old ratio (90% in this example) and 0%, while + "or" gives one at the middle of the old ratio and 100% The corresponding + binary operations for fixed-point fractions are: "right-shift by one and + insert a 0 behind the fixed point" and "right-shift by one and insert a 1 + behind the fixed point" respecatbly. + + 115/128 = 89.84% (near 90%) In binary fix-point: 0.1110011 + 0.01110011 = 115/256 = 44.92% + 0.11110011 = 243/256 = 94.92% + + So to achieve the desired ratio, start at the LSB (right end) of + 'numerator'. Initialize the output bits to zero. Conduct an "and" for each + 0 and an "or" for each 1 with a freshly drawn random number until the fixed + point is reached. + + An "and" operation of a random number and zero always yields zero. To avoid + waste, we reduce terms to eliminate the trailing zeroes in 'numerator' and + indicate the fixed point with 'precision'. Each time the program is + executed the location of the fixed point is set anew, but it stays constant + until the program exits. +----------------------------------------------------------------------------*/ + unsigned int i; + uint32_t mask; + uint32_t retval; + + for (i = 0, mask = 0x01, retval=0x00000000; + i < precision; + ++i, mask <<= 1) { + + uint32_t const randval = pm_rand32(randStP); + + if ((numerator & mask) != 0 ) + retval |= randval; + else + retval &= randval; + } + return retval; +} + + + +static uint32_t +swapWord(uint32_t const word) { +/*---------------------------------------------------------------------------- + Swap four bytes. + This swap method works regardless of native system endianness. +----------------------------------------------------------------------------*/ + uint32_t const retval = + ((word >> 24) & 0xff) | + ((word >> 8) & 0xff00) | + ((word << 8) & 0xff0000) | + ((word << 24) & 0xff000000) + ; + + return retval; +} + + + +static void +swapBitrow(unsigned char * const bitrow, + unsigned int const words, + bool const bswap) { +/*---------------------------------------------------------------------------- + Modify bits in 'bitrow', swapping as indicated. +----------------------------------------------------------------------------*/ + uint32_t * const bitrowByWord = (uint32_t *) bitrow; + + unsigned int wordCnt; + + for (wordCnt=0; wordCnt < words; ++wordCnt) { + uint32_t const inWord = bitrowByWord[wordCnt]; + + bitrowByWord[wordCnt] = bswap ? swapWord(inWord) : inWord; + } +} + + + +static void +pbmnoise(FILE * const ofP, + unsigned int const cols, + unsigned int const rows, + unsigned int const numerator, + unsigned int const precision, + bool const bswap, + struct pm_randSt * const randStP) { +/*---------------------------------------------------------------------------- + Default method of constructing rows. + + Generate pixels in units of 32 bits. + + If cols is not a multiple of 32, discard pixels beyond row end. +-----------------------------------------------------------------------------*/ + unsigned int const words = (cols + 31) / 32; + + unsigned char * bitrow; + unsigned int row; + unsigned int wordCnt; + + bitrow = pbm_allocrow_packed(cols + 32); + + for (row = 0; row < rows; ++row) { + uint32_t * const bitrowByWord = (uint32_t *) bitrow; + + for (wordCnt = 0; wordCnt < words; ++wordCnt) + bitrowByWord[wordCnt] = randombits(precision, numerator, randStP); + + if (bswap) + swapBitrow(bitrow, words, bswap); + + pbm_cleanrowend_packed(bitrow, cols); + pbm_writepbmrow_packed(ofP, bitrow, cols, 0); + } + pbm_freerow(bitrow); +} + + + +static void +pbmnoise_packed(FILE * const ofP, + unsigned int const cols, + unsigned int const rows, + unsigned int const numerator, + unsigned int const precision, + bool const bswap, + struct pm_randSt * const randStP) { +/*---------------------------------------------------------------------------- + Alternate method of constructing rows. + Like the default pbmnoise(), generate pixels in units of 32 bits + but carry over unused pixel data at row end to the next row. +-----------------------------------------------------------------------------*/ + unsigned char * bitrow0; + uint32_t * bitrowByWord; + unsigned int offset; + unsigned int row; + uint32_t wordSave; /* Pixels carried over to next row */ + + bitrow0 = pbm_allocrow_packed(cols + 63); + bitrowByWord = (uint32_t *) bitrow0; + + for (row = 0, offset = 0; row < rows; ++row) { + if (offset == 0) { + unsigned int const words = (cols + 31 ) / 32; + + unsigned int wordCnt; + + for (wordCnt = 0; wordCnt< words; ++wordCnt) { + bitrowByWord[wordCnt] = + randombits(precision, numerator, randStP); + } + + if (bswap) + swapBitrow(bitrow0, words, bswap); + + wordSave = bitrowByWord[words - 1]; + + pbm_writepbmrow_packed(ofP, bitrow0, cols, 0); + offset = cols % 32; + } else { + unsigned int const wordsToFetch = (cols - (32 - offset) + 31) / 32; + unsigned int const lastWord = wordsToFetch; + + unsigned int wordCnt; + + bitrowByWord[0] = wordSave; + + for (wordCnt = 0; wordCnt < wordsToFetch; ++wordCnt) { + bitrowByWord[wordCnt + 1] = + randombits(precision, numerator, randStP); + } + + if (bswap) + swapBitrow((unsigned char *) & bitrowByWord[1], + wordsToFetch, bswap); + + wordSave = bitrowByWord [lastWord]; + + pbm_writepbmrow_bitoffset(ofP, bitrow0, cols, 0, offset); + offset = (offset + cols) % 32; + } + } + pbm_freerow(bitrow0); +} + + +int +main(int argc, const char *argv[]) { + + struct CmdlineInfo cmdline; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + pbm_writepbminit(stdout, cmdline.width, cmdline.height, 0); + + if (cmdline.precision == 0) { + bit color; + + if (cmdline.numerator == 0) + color = PBM_WHITE; + else { + assert (cmdline.numerator == 1); + color = PBM_BLACK; + } + writeSingleColorRaster(cmdline.width, cmdline.height, color, stdout); + } else if (cmdline.width % 32 == 0 || !cmdline.pack) { + struct pm_randSt randSt; + + pm_randinit(&randSt); + pm_srand2(&randSt, cmdline.randomseedSpec, cmdline.randomseed); + + pbmnoise(stdout, cmdline.width, cmdline.height, + cmdline.numerator, cmdline.precision, + cmdline.bswap, &randSt); + + pm_randterm(&randSt); + } else { + struct pm_randSt randSt; + + pm_randinit(&randSt); + pm_srand2(&randSt, cmdline.randomseedSpec, cmdline.randomseed); + + pbmnoise_packed(stdout, cmdline.width, cmdline.height, + cmdline.numerator, cmdline.precision, + cmdline.bswap, &randSt); + + pm_randterm(&randSt); + } + return 0; +} + + diff --git a/generator/pbmtext.c b/generator/pbmtext.c index 7ea64857..a4566d12 100644 --- a/generator/pbmtext.c +++ b/generator/pbmtext.c @@ -1282,6 +1282,8 @@ computeImageWidth(struct Text const formattedText, unsigned int * const colsP, unsigned int * const maxleftbP) { + assert (pbm_maxfontwidth() < (INT_MAX - 10) / LINEBUFSIZE); + if (intercharacterSpace < 0 && fontP->maxwidth < -intercharacterSpace) pm_error("negative -space value %.2f exceeds font width", intercharacterSpace); diff --git a/generator/ppmmake.c b/generator/ppmmake.c index 7bac9601..b1de7b52 100644 --- a/generator/ppmmake.c +++ b/generator/ppmmake.c @@ -31,11 +31,11 @@ static void parseCommandLine(int argc, char ** argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- - Convert program invocation arguments (argc,argv) into a format the + Convert program invocation arguments (argc,argv) into a format the program can use easily, struct cmdlineInfo. Validate arguments along the way and exit program with message if invalid. - Note that some string information we return as *cmdlineP is in the storage + Note that some string information we return as *cmdlineP is in the storage argv[] points to. -----------------------------------------------------------------------------*/ optEntry * option_def; diff --git a/generator/ppmpat.c b/generator/ppmpat.c index 9473afeb..170bfc58 100644 --- a/generator/ppmpat.c +++ b/generator/ppmpat.c @@ -39,9 +39,10 @@ typedef enum { PAT_POLES, PAT_SQUIG, PAT_CAMO, - PAT_ANTICAMO, + PAT_ANTICAMO } Pattern; + typedef struct { /*---------------------------------------------------------------------------- An ordered list of colors with a cursor. @@ -57,16 +58,79 @@ struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ - Pattern basePattern; - unsigned int width; - unsigned int height; - unsigned int colorSpec; - ColorTable colorTable; - unsigned int randomseed; - unsigned int randomseedSpec; + Pattern basePattern; + unsigned int width; + unsigned int height; + unsigned int colorSpec; + ColorTable colorTable; + unsigned int randomseed; + unsigned int randomseedSpec; + ppmd_drawproc * drawProc; }; + +static pixel +averageTwoColors(pixel const p1, + pixel const p2) { + + pixel p; + + PPM_ASSIGN(p, + (PPM_GETR(p1) + PPM_GETR(p2)) / 2, + (PPM_GETG(p1) + PPM_GETG(p2)) / 2, + (PPM_GETB(p1) + PPM_GETB(p2)) / 2); + + return p; +} + + + +static ppmd_drawproc average_drawproc; + +static void +average_drawproc(pixel ** const pixels, + int const cols, + int const rows, + pixval const maxval, + int const col, + int const row, + const void * const clientdata) { +/*---------------------------------------------------------------------------- + Reset the pixel's color to the average of the original color and the color + indicated by * clientdata. +-----------------------------------------------------------------------------*/ + + if (col >= 0 && col < cols && row >= 0 && row < rows) + pixels[row][col] = + averageTwoColors(pixels[row][col], *((const pixel*) clientdata)); +} + + + +static ppmd_drawproc checkerboard_drawproc; + +static void +checkerboard_drawproc(pixel ** const pixels, + int const cols, + int const rows, + pixval const maxval, + int const col, + int const row, + const void * const clientdata) { +/*---------------------------------------------------------------------------- + If col and row are both even or both odd, do nothing. + If one is even and the other is odd, set the pixel's color to that indicated + by * clientdata. +-----------------------------------------------------------------------------*/ + if (col >= 0 && col < cols && row >= 0 && + row < rows && row % 2 != col % 2) + + pixels[row][col] = *((const pixel*) clientdata); +} + + + static void validateColorCount(Pattern const basePattern, unsigned int const colorCount) { @@ -182,6 +246,7 @@ parseCommandLine(int argc, const char ** argv, unsigned int squig; unsigned int camo; unsigned int anticamo; + unsigned int meshSpec; MALLOCARRAY_NOFAIL(option_def, 100); @@ -199,9 +264,9 @@ parseCommandLine(int argc, const char ** argv, OPTENT3(0, "tartan", OPT_FLAG, NULL, &tartan, 0); OPTENT3(0, "argyle1", OPT_FLAG, NULL, - &argyle1, 0); + &argyle1, 0); OPTENT3(0, "argyle2", OPT_FLAG, NULL, - &argyle2, 0); + &argyle2, 0); OPTENT3(0, "poles", OPT_FLAG, NULL, &poles, 0); OPTENT3(0, "squig", OPT_FLAG, NULL, @@ -214,6 +279,8 @@ parseCommandLine(int argc, const char ** argv, &cmdlineP->colorSpec, 0); OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomseed, &cmdlineP->randomseedSpec, 0); + OPTENT3(0, "mesh", OPT_FLAG, NULL, + &meshSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -265,6 +332,14 @@ parseCommandLine(int argc, const char ** argv, } else cmdlineP->colorTable.count = 0; + if (meshSpec) { + if (gingham2 + gingham3 + madras + tartan > 0) + cmdlineP->drawProc = &checkerboard_drawproc; + else + pm_message("-mesh ignored (no effect with specified pattern)"); + } else + cmdlineP->drawProc = &average_drawproc; + if (argc-1 != 2) pm_error("You must specify 2 non-option arguments: width and height " "in pixels. You specified %u", argc-1); @@ -363,37 +438,6 @@ randomDarkColor(struct pm_randSt * const randStP, -static pixel -averageTwoColors(pixel const p1, - pixel const p2) { - - pixel p; - - PPM_ASSIGN(p, - (PPM_GETR(p1) + PPM_GETR(p2)) / 2, - (PPM_GETG(p1) + PPM_GETG(p2)) / 2, - (PPM_GETB(p1) + PPM_GETB(p2)) / 2); - - return p; -} - - - -static ppmd_drawproc average_drawproc; - -static void -average_drawproc(pixel ** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void * const clientdata) { - - if (col >= 0 && col < cols && row >= 0 && row < rows) - pixels[row][col] = - averageTwoColors(pixels[row][col], *((const pixel*) clientdata)); -} @@ -563,7 +607,7 @@ clearBackgroundCamo(pixel ** const pixels, } else if (antiflag) color = randomAnticamoColor(randStP, maxval); else - color = randomCamoColor(randStP,maxval); + color = randomCamoColor(randStP, maxval); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, @@ -704,6 +748,7 @@ gingham2(pixel ** const pixels, unsigned int const rows, ColorTable const colorTable, struct pm_randSt * const randStP, + ppmd_drawproc * const drawproc, pixval const maxval) { bool const colorSpec = (colorTable.count > 0); @@ -726,11 +771,11 @@ gingham2(pixel ** const pixels, /* Woof. */ ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rowso2, average_drawproc, + pixels, cols, rows, maxval, 0, 0, cols, rowso2, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rowso2, cols, rows - rowso2, - average_drawproc, &forecolor); + drawproc, &forecolor); } @@ -741,6 +786,7 @@ gingham3(pixel ** const pixels, unsigned int const rows, ColorTable const colorTable, struct pm_randSt * const randStP, + ppmd_drawproc * const drawproc, pixval const maxval) { bool const colorSpec = (colorTable.count > 0); @@ -772,17 +818,17 @@ gingham3(pixel ** const pixels, /* Woof. */ ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rowso4, average_drawproc, + pixels, cols, rows, maxval, 0, 0, cols, rowso4, drawproc, &backcolor); ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, average_drawproc, + pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rowso4, cols, rowso4, - average_drawproc, &fore2color); + drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rowso4, cols, rows - rowso4, - average_drawproc, &fore1color); + drawproc, &fore1color); } @@ -793,6 +839,7 @@ madras(pixel ** const pixels, unsigned int const rows, ColorTable const colorTable, struct pm_randSt * const randStP, + ppmd_drawproc * const drawproc, pixval const maxval) { bool const colorSpec = (colorTable.count > 0); @@ -868,54 +915,54 @@ madras(pixel ** const pixels, /* Woof. */ ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows2, average_drawproc, + pixels, cols, rows, maxval, 0, 0, cols, rows2, drawproc, &backcolor); ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, rows2, cols, rows3, average_drawproc, + pixels, cols, rows, maxval, 0, rows2, cols, rows3, drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows2 + rows3, cols, rows2, - average_drawproc, &backcolor); + drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rows2 + rows3, cols, rows2, - average_drawproc, &fore1color); + drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rows2 + rows3, cols, rows2, - average_drawproc, &backcolor); + drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3, cols, rows6a, - average_drawproc, &fore2color); + drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3 + rows6a, cols, rows2, - average_drawproc, &backcolor); + drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + rows3 + rows6a, cols, rows3, - average_drawproc, &fore1color); + drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + 2 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor); + rows2, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 2 * rows3 + rows6a, cols, - rows3, average_drawproc, &fore1color); + rows3, drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 3 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor); + rows2, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a, cols, - rows6b, average_drawproc, &fore2color); + rows6b, drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor); + cols, rows2, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 8 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &fore1color); + cols, rows2, drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 9 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor); + cols, rows2, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 10 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows3, average_drawproc, &fore2color); + cols, rows3, drawproc, &fore2color); } @@ -926,6 +973,7 @@ tartan(pixel ** const pixels, unsigned int const rows, ColorTable const colorTable, struct pm_randSt * const randStP, + ppmd_drawproc * const drawproc, pixval const maxval) { bool const colorSpec = (colorTable.count > 0); @@ -977,29 +1025,29 @@ tartan(pixel ** const pixels, /* Woof. */ ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows5a, average_drawproc, + pixels, cols, rows, maxval, 0, 0, cols, rows5a, drawproc, &backcolor); ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, rows5a, cols, rows1, average_drawproc, + pixels, cols, rows, maxval, 0, rows5a, cols, rows1, drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows5a + rows1, cols, rows5b, - average_drawproc, &backcolor); + drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1, cols, rows3, - average_drawproc, &fore2color); + drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1 + rows3, cols, rows1, - average_drawproc, &backcolor); + drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + rows3, cols, rows3, - average_drawproc, &fore2color); + drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + 2 * rows3, cols, - rows1, average_drawproc, &backcolor); + rows1, drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 3 * rows1 + 2 * rows3, cols, - rows3, average_drawproc, &fore2color); + rows3, drawproc, &fore2color); } @@ -1077,7 +1125,7 @@ argyle(pixel ** const pixels, -static unsigned int const MAXPOLES = 500; +#define MAXPOLES 500 @@ -1541,22 +1589,22 @@ main(int argc, const char ** argv) { switch (cmdline.basePattern) { case PAT_GINGHAM2: gingham2(pixels, cmdline.width, cmdline.height, - cmdline.colorTable, &randSt, PPM_MAXMAXVAL); + cmdline.colorTable, &randSt, cmdline.drawProc, PPM_MAXMAXVAL); break; case PAT_GINGHAM3: gingham3(pixels, cmdline.width, cmdline.height, - cmdline.colorTable, &randSt, PPM_MAXMAXVAL); + cmdline.colorTable, &randSt, cmdline.drawProc, PPM_MAXMAXVAL); break; case PAT_MADRAS: madras(pixels, cmdline.width, cmdline.height, - cmdline.colorTable, &randSt, PPM_MAXMAXVAL); + cmdline.colorTable, &randSt, cmdline.drawProc, PPM_MAXMAXVAL); break; case PAT_TARTAN: tartan(pixels, cmdline.width, cmdline.height, - cmdline.colorTable, &randSt, PPM_MAXMAXVAL); + cmdline.colorTable, &randSt, cmdline.drawProc, PPM_MAXMAXVAL); break; case PAT_ARGYLE1: |