diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2009-09-27 21:44:29 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2009-09-27 21:44:29 +0000 |
commit | 43939e66b1d4eeb2f3799c124f3598756755005a (patch) | |
tree | 15733092de55d52421a6ea02f5a43d5f8ff24393 /generator/ppmpat.c | |
parent | 49f4336c9bba33650573ba780b70bc501b38643e (diff) | |
download | netpbm-mirror-43939e66b1d4eeb2f3799c124f3598756755005a.tar.gz netpbm-mirror-43939e66b1d4eeb2f3799c124f3598756755005a.tar.xz netpbm-mirror-43939e66b1d4eeb2f3799c124f3598756755005a.zip |
Rebase Stable series to current Advanced: 10.47.04
git-svn-id: http://svn.code.sf.net/p/netpbm/code/stable@995 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator/ppmpat.c')
-rw-r--r-- | generator/ppmpat.c | 1375 |
1 files changed, 741 insertions, 634 deletions
diff --git a/generator/ppmpat.c b/generator/ppmpat.c index 9e2f6d05..82acafae 100644 --- a/generator/ppmpat.c +++ b/generator/ppmpat.c @@ -12,17 +12,244 @@ #define _XOPEN_SOURCE /* get M_PI in math.h */ +#include <assert.h> #include <math.h> +#include <limits.h> #include "pm_c_util.h" +#include "mallocvar.h" +#include "shhopt.h" #include "ppm.h" #include "ppmdraw.h" +typedef enum { + PAT_GINGHAM2, + PAT_GINGHAM3, + PAT_MADRAS, + PAT_TARTAN, + PAT_POLES, + PAT_SQUIG, + PAT_CAMO, + PAT_ANTICAMO +} pattern; + +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; +}; + + + +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 OptParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int basePatternCount; + unsigned int gingham2; + unsigned int gingham3; + unsigned int madras; + unsigned int tartan; + unsigned int poles; + unsigned int squig; + unsigned int camo; + unsigned int anticamo; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "gingham2", OPT_FLAG, NULL, &gingham2, 0); + OPTENT3(0, "g2", OPT_FLAG, NULL, &gingham2, 0); + OPTENT3(0, "gingham3", OPT_FLAG, NULL, &gingham3, 0); + OPTENT3(0, "g3", OPT_FLAG, NULL, &gingham3, 0); + OPTENT3(0, "madras", OPT_FLAG, NULL, &madras, 0); + OPTENT3(0, "tartan", OPT_FLAG, NULL, &tartan, 0); + OPTENT3(0, "poles", OPT_FLAG, NULL, &poles, 0); + OPTENT3(0, "squig", OPT_FLAG, NULL, &squig, 0); + OPTENT3(0, "camo", OPT_FLAG, NULL, &camo, 0); + OPTENT3(0, "anticamo", OPT_FLAG, NULL, &anticamo, 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, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + basePatternCount = + gingham2 + + gingham3 + + madras + + tartan + + poles + + squig + + camo + + anticamo; + + if (basePatternCount < 1) + pm_error("You must specify a base pattern option such as -gingham2"); + else if (basePatternCount > 1) + pm_error("You may not specify more than one base pattern option. " + "You specified %u", basePatternCount); + else { + if (gingham2) + cmdlineP->basePattern = PAT_GINGHAM2; + else if (gingham3) + cmdlineP->basePattern = PAT_GINGHAM3; + else if (madras) + cmdlineP->basePattern = PAT_MADRAS; + else if (tartan) + cmdlineP->basePattern = PAT_TARTAN; + else if (poles) + cmdlineP->basePattern = PAT_POLES; + else if (squig) + cmdlineP->basePattern = PAT_SQUIG; + else if (camo) + cmdlineP->basePattern = PAT_CAMO; + else if (anticamo) + cmdlineP->basePattern = PAT_ANTICAMO; + else + assert(false); /* Every possibility is accounted for */ + } + if (argc-1 != 2) + pm_error("You must specify 2 non-option arguments: width and height " + "in pixels. You specified %u", argc-1); + else { + cmdlineP->width = atoi(argv[1]); + cmdlineP->height = atoi(argv[2]); + + if (cmdlineP->width < 1) + pm_error("Width must be at least 1 pixel"); + if (cmdlineP->height < 1) + pm_error("Height must be at least 1 pixel"); + } +} + + + +static void +validateComputableDimensions(unsigned int const cols, + unsigned int const rows) { + + /* + Notes on width and height limits: + + cols * 3, rows * 3 appear in madras, tartan + cols*rows appears in poles + cols+rows appears in squig + + PPMD functions use signed integers for pixel positions + (because they allow you to specify points off the canvas). + */ + + if (cols > INT_MAX/4 || rows > INT_MAX/4 || rows > INT_MAX/cols) + pm_error("Width and/or height are way too large: %u x %u", + cols, rows); +} + + + +static pixel +randomColor(pixval const maxval) { + + pixel p; + + PPM_ASSIGN(p, + rand() % (maxval + 1), + rand() % (maxval + 1), + rand() % (maxval + 1) + ); + + return p; +} + + + +#define DARK_THRESH 0.25 + +static pixel +randomBrightColor(pixval const maxval) { + + pixel p; + + do { + p = randomColor(maxval); + } while (PPM_LUMIN(p) <= maxval * DARK_THRESH); + + return p; +} + + + +static pixel +randomDarkColor(pixval const maxval) { + + pixel p; + + do { + p = randomColor(maxval); + } while (PPM_LUMIN(p) > maxval * DARK_THRESH); + + return p; +} + + + +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)); +} + + + +/*---------------------------------------------------------------------------- + Camouflage stuff +-----------------------------------------------------------------------------*/ + static pixel -random_anticamo_color(pixval const maxval) { +randomAnticamoColor(pixval const maxval) { int v1, v2, v3; pixel p; @@ -70,17 +297,14 @@ random_anticamo_color(pixval const maxval) { -/* Camouflage stuff. */ - static pixel -random_camo_color(pixval const maxval) { +randomCamoColor(pixval const maxval) { - int v1, v2, v3; - pixel p; + int const v1 = (maxval + 1 ) / 8; + int const v2 = (maxval + 1 ) / 4; + int const v3 = (maxval + 1 ) / 2; - v1 = (maxval + 1 ) / 8; - v2 = (maxval + 1 ) / 4; - v3 = (maxval + 1 ) / 2; + pixel p; switch (rand() % 10) { case 0: @@ -122,6 +346,46 @@ rnduni(void) { +static void +clearBackground(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + bool const antiflag) { + + pixel color; + + if (antiflag) + color = randomAnticamoColor(maxval); + else + color = randomCamoColor(maxval); + + ppmd_filledrectangle( + pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, + &color); +} + + +static void +camoFill(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + struct fillobj * const fh, + bool const antiflag) { + + pixel color; + + if (antiflag) + color = randomAnticamoColor(maxval); + else + color = randomCamoColor(maxval); + + ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); +} + + + #define BLOBRAD 50 #define MIN_POINTS 7 @@ -136,63 +400,68 @@ rnduni(void) { static void +computeXsYs(int * const xs, + int * const ys, + unsigned int const cols, + unsigned int const rows, + unsigned int const pointCt) { + + unsigned int const cx = rand() % cols; + unsigned int const cy = rand() % rows; + double const a = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + + MIN_ELLIPSE_FACTOR; + double const b = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + + MIN_ELLIPSE_FACTOR; + double const theta = rnduni() * 2.0 * M_PI; + + unsigned int p; + + for (p = 0; p < pointCt; ++p) { + double const c = rnduni() * (MAX_POINT_FACTOR - MIN_POINT_FACTOR) + + MIN_POINT_FACTOR; + double const tx = a * sin(p * 2.0 * M_PI / pointCt); + double const ty = b * cos(p * 2.0 * M_PI / pointCt); + double const tang = atan2(ty, tx) + theta; + xs[p] = MAX(0, MIN(cols-1, cx + BLOBRAD * c * sin(tang))); + ys[p] = MAX(0, MIN(rows-1, cy + BLOBRAD * c * cos(tang))); + } +} + + + +static void camo(pixel ** const pixels, unsigned int const cols, unsigned int const rows, pixval const maxval, bool const antiflag) { - pixel color; - int n, i, cx, cy; - struct fillobj * fh; + unsigned int const n = (rows * cols) / (BLOBRAD * BLOBRAD) * 5; - /* Clear background. */ - if (antiflag) - color = random_anticamo_color( maxval ); - else - color = random_camo_color( maxval ); + unsigned int i; - ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color); + clearBackground(pixels, cols, rows, maxval, antiflag); - n = (rows * cols) / (BLOBRAD * BLOBRAD) * 5; for (i = 0; i < n; ++i) { - int points, p, xs[MAX_POINTS], ys[MAX_POINTS], x0, y0; - float a, b, c, theta, tang, tx, ty; - - cx = rand() % cols; - cy = rand() % rows; - - points = rand() % ( MAX_POINTS - MIN_POINTS + 1 ) + MIN_POINTS; - a = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + - MIN_ELLIPSE_FACTOR; - b = rnduni() * (MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR) + - MIN_ELLIPSE_FACTOR; - theta = rnduni() * 2.0 * M_PI; - for (p = 0; p < points; ++p) { - tx = a * sin(p * 2.0 * M_PI / points); - ty = b * cos(p * 2.0 * M_PI / points); - tang = atan2(ty, tx) + theta; - c = rnduni() * (MAX_POINT_FACTOR - MIN_POINT_FACTOR) + - MIN_POINT_FACTOR; - xs[p] = cx + BLOBRAD * c * sin(tang); - ys[p] = cy + BLOBRAD * c * cos(tang); - } - x0 = (xs[0] + xs[points - 1]) / 2; - y0 = (ys[0] + ys[points - 1]) / 2; + unsigned int const pointCt = + rand() % (MAX_POINTS - MIN_POINTS + 1) + MIN_POINTS; + + int xs[MAX_POINTS], ys[MAX_POINTS]; + int x0, y0; + struct fillobj * fh; + + computeXsYs(xs, ys, cols, rows, pointCt); + + x0 = (xs[0] + xs[pointCt - 1]) / 2; + y0 = (ys[0] + ys[pointCt - 1]) / 2; fh = ppmd_fill_create(); ppmd_polyspline( - pixels, cols, rows, maxval, x0, y0, points, xs, ys, x0, y0, - ppmd_fill_drawproc, fh ); + pixels, cols, rows, maxval, x0, y0, pointCt, xs, ys, x0, y0, + ppmd_fill_drawproc, fh); - if (antiflag) - color = random_anticamo_color(maxval); - else - color = random_camo_color(maxval); - ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); + camoFill(pixels, cols, rows, maxval, fh, antiflag); ppmd_fill_destroy(fh); } @@ -200,499 +469,454 @@ camo(pixel ** const pixels, -static pixel -random_color(pixval const maxval) { - - pixel p; - - PPM_ASSIGN(p, - rand() % (maxval + 1), - rand() % (maxval + 1), - rand() % (maxval + 1) - ); - - return p; -} - - - -#define DARK_THRESH 0.25 +/*---------------------------------------------------------------------------- + Gingham stuff +-----------------------------------------------------------------------------*/ -#if __STDC__ -static pixel -random_bright_color( pixval maxval ) -#else /*__STDC__*/ -static pixel -random_bright_color( maxval ) - pixval maxval; -#endif /*__STDC__*/ - { - pixel p; - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) <= maxval * DARK_THRESH ); - - return p; - } - -#if __STDC__ -static pixel -random_dark_color( pixval maxval ) -#else /*__STDC__*/ -static pixel -random_dark_color( maxval ) - pixval maxval; -#endif /*__STDC__*/ - { - pixel p; - - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) > maxval * DARK_THRESH ); - - return p; - } - -static pixel -average_two_colors( p1, p2 ) -pixel p1, p2; - { - pixel p; - - PPM_ASSIGN( - p, ( (int) PPM_GETR(p1) + (int) PPM_GETR(p2) ) / 2, - ( (int) PPM_GETG(p1) + (int) PPM_GETG(p2) ) / 2, - ( (int) PPM_GETB(p1) + (int) PPM_GETB(p2) ) / 2 ); - - return p; - } - -/* Gingham stuff. */ 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] = - average_two_colors( pixels[row][col], *( (pixel*) clientdata ) ); -} +gingham2(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { -static void -gingham2( pixel** pixels, int cols, int rows, pixval maxval ) -{ - pixel const backcolor = random_dark_color( maxval ); - pixel const forecolor = random_bright_color( maxval ); - int const colso2 = cols / 2; - int const rowso2 = rows / 2; + pixel const backcolor = randomDarkColor(maxval); + pixel const forecolor = randomBrightColor(maxval); + unsigned int const colso2 = cols / 2; + unsigned int const rowso2 = rows / 2; /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, colso2, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, colso2, 0, cols - colso2, rows, - PPMD_NULLDRAWPROC, &forecolor ); + PPMD_NULLDRAWPROC, &forecolor); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rowso2, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rowso2, cols, rows - rowso2, - average_drawproc, &forecolor ); - } + average_drawproc, &forecolor); +} + + -#if __STDC__ -static void -gingham3( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -gingham3( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int colso4, rowso4; - pixel backcolor, fore1color, fore2color; - - colso4 = cols / 4; - rowso4 = rows / 4; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +gingham3(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const colso4 = cols / 4; + unsigned int const rowso4 = rows / 4; + + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, colso4, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, colso4, 0, colso4, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 2 * colso4, 0, colso4, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 3 * colso4, 0, cols - colso4, rows, - PPMD_NULLDRAWPROC, &fore1color ); + PPMD_NULLDRAWPROC, &fore1color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rowso4, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, average_drawproc, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rowso4, cols, rowso4, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rowso4, cols, rows - rowso4, - average_drawproc, &fore1color ); - } + average_drawproc, &fore1color); +} + + -#if __STDC__ -static void -madras( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -madras( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int cols2, rows2, cols3, rows3, cols12, rows12, cols6a, rows6a, cols6b, - rows6b; - pixel backcolor, fore1color, fore2color; - - cols2 = cols * 2 / 44; - rows2 = rows * 2 / 44; - cols3 = cols * 3 / 44; - rows3 = rows * 3 / 44; - cols12 = cols - 10 * cols2 - 4 * cols3; - rows12 = rows - 10 * rows2 - 4 * rows3; - cols6a = cols12 / 2; - rows6a = rows12 / 2; - cols6b = cols12 - cols6a; - rows6b = rows12 - rows6a; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +madras(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const cols2 = cols * 2 / 44; + unsigned int const rows2 = rows * 2 / 44; + unsigned int const cols3 = cols * 3 / 44; + unsigned int const rows3 = rows * 3 / 44; + unsigned int const cols12 = cols - 10 * cols2 - 4 * cols3; + unsigned int const rows12 = rows - 10 * rows2 - 4 * rows3; + unsigned int const cols6a = cols12 / 2; + unsigned int const rows6a = rows12 / 2; + unsigned int const cols6b = cols12 - cols6a; + unsigned int const rows6b = rows12 - rows6a; + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols2, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols2, 0, cols3, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 2 * cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 3 * cols2 + cols3, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 4 * cols2 + cols3, 0, cols6a, rows, - PPMD_NULLDRAWPROC, &fore1color ); + PPMD_NULLDRAWPROC, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 4 * cols2 + cols3 + cols6a, 0, cols2, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 5 * cols2 + cols3 + cols6a, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 5 * cols2 + 2 * cols3 + cols6a, 0, cols2, - rows, PPMD_NULLDRAWPROC, &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 6 * cols2 + 2 * cols3 + cols6a, 0, cols3, - rows, PPMD_NULLDRAWPROC, &fore2color ); + rows, PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 6 * cols2 + 3 * cols3 + cols6a, 0, cols2, - rows, PPMD_NULLDRAWPROC, &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a, 0, cols6b, - rows, PPMD_NULLDRAWPROC, &fore1color ); + rows, PPMD_NULLDRAWPROC, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); + cols2, rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 8 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &fore2color ); + cols2, rows, PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 9 * cols2 + 3 * cols3 + cols6a + cols6b, 0, - cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); + cols2, rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 10 * cols2 + 3 * cols3 + cols6a + cols6b, - 0, cols3, rows, PPMD_NULLDRAWPROC, &fore1color ); + 0, cols3, rows, PPMD_NULLDRAWPROC, &fore1color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows2, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows2, cols, rows3, average_drawproc, - &fore2color ); + &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows2 + rows3, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 2 * rows2 + rows3, cols, rows2, - average_drawproc, &fore1color ); + average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 3 * rows2 + rows3, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3, cols, rows6a, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 4 * rows2 + rows3 + rows6a, cols, rows2, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + rows3 + rows6a, cols, rows3, - average_drawproc, &fore1color ); + average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 5 * rows2 + 2 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor ); + rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 2 * rows3 + rows6a, cols, - rows3, average_drawproc, &fore1color ); + rows3, average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 6 * rows2 + 3 * rows3 + rows6a, cols, - rows2, average_drawproc, &backcolor ); + rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a, cols, - rows6b, average_drawproc, &fore2color ); + rows6b, average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor ); + cols, rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 8 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &fore1color ); + cols, rows2, average_drawproc, &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 9 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows2, average_drawproc, &backcolor ); + cols, rows2, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 10 * rows2 + 3 * rows3 + rows6a + rows6b, - cols, rows3, average_drawproc, &fore2color ); - } + cols, rows3, average_drawproc, &fore2color); +} + + -#if __STDC__ -static void -tartan( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ static void -tartan( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int cols1, rows1, cols3, rows3, cols10, rows10, cols5a, rows5a, cols5b, - rows5b; - pixel backcolor, fore1color, fore2color; - - cols1 = cols / 22; - rows1 = rows / 22; - cols3 = cols * 3 / 22; - rows3 = rows * 3 / 22; - cols10 = cols - 3 * cols1 - 3 * cols3; - rows10 = rows - 3 * rows1 - 3 * rows3; - cols5a = cols10 / 2; - rows5a = rows10 / 2; - cols5b = cols10 - cols5a; - rows5b = rows10 - rows5a; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); +tartan(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const cols1 = cols / 22; + unsigned int const rows1 = rows / 22; + unsigned int const cols3 = cols * 3 / 22; + unsigned int const rows3 = rows * 3 / 22; + unsigned int const cols10 = cols - 3 * cols1 - 3 * cols3; + unsigned int const rows10 = rows - 3 * rows1 - 3 * rows3; + unsigned int const cols5a = cols10 / 2; + unsigned int const rows5a = rows10 / 2; + unsigned int const cols5b = cols10 - cols5a; + unsigned int const rows5b = rows10 - rows5a; + pixel const backcolor = randomDarkColor(maxval); + pixel const fore1color = randomBrightColor(maxval); + pixel const fore2color = randomBrightColor(maxval); /* Warp. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols5a, rows, PPMD_NULLDRAWPROC, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols5a, 0, cols1, rows, PPMD_NULLDRAWPROC, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols5a + cols1, 0, cols5b, rows, PPMD_NULLDRAWPROC, &backcolor ); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + cols1, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + cols1 + cols3, 0, cols1, rows, - PPMD_NULLDRAWPROC, &backcolor ); + PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 2 * cols1 + cols3, 0, cols3, rows, - PPMD_NULLDRAWPROC, &fore2color ); + PPMD_NULLDRAWPROC, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 2 * cols1 + 2 * cols3, 0, cols1, - rows, PPMD_NULLDRAWPROC, (char*) &backcolor ); + rows, PPMD_NULLDRAWPROC, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, cols10 + 3 * cols1 + 2 * cols3, 0, cols3, - rows, PPMD_NULLDRAWPROC, &fore2color ); + rows, PPMD_NULLDRAWPROC, &fore2color); /* Woof. */ ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows5a, average_drawproc, - &backcolor ); + &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows5a, cols, rows1, average_drawproc, - &fore1color ); + &fore1color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows5a + rows1, cols, rows5b, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1, cols, rows3, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + rows1 + rows3, cols, rows1, - average_drawproc, &backcolor ); + average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + rows3, cols, rows3, - average_drawproc, &fore2color ); + average_drawproc, &fore2color); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + 2 * rows3, cols, - rows1, average_drawproc, &backcolor ); + rows1, average_drawproc, &backcolor); ppmd_filledrectangle( pixels, cols, rows, maxval, 0, rows10 + 3 * rows1 + 2 * rows3, cols, - rows3, average_drawproc, &fore2color ); - } + rows3, average_drawproc, &fore2color); +} + + + +/*---------------------------------------------------------------------------- + Poles stuff +-----------------------------------------------------------------------------*/ + -/* Poles stuff. */ #define MAXPOLES 500 -#if __STDC__ -static void -poles( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ + + static void -poles( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { - int poles, i, xs[MAXPOLES], ys[MAXPOLES], col, row; - pixel colors[MAXPOLES]; +placeAndColorPolesRandomly(int * const xs, + int * const ys, + pixel * const colors, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + unsigned int const poleCt) { - poles = cols * rows / 30000; + unsigned int i; - /* Place and color poles randomly. */ - for ( i = 0; i < poles; ++i ) - { - xs[i] = rand() % cols; - ys[i] = rand() % rows; - colors[i] = random_bright_color( maxval ); + for (i = 0; i < poleCt; ++i) { + xs[i] = rand() % cols; + ys[i] = rand() % rows; + colors[i] = randomBrightColor(maxval); } +} - /* Now interpolate points. */ - for ( row = 0; row < rows; ++row ) - for ( col = 0; col < cols; ++col ) - { - register long dist1, dist2, newdist, r, g, b; - pixel color1, color2; - /* Find two closest poles. */ - dist1 = dist2 = 2000000000; - for ( i = 0; i < poles; ++i ) - { - newdist = ( col - xs[i] ) * ( col - xs[i] ) + - ( row - ys[i] ) * ( row - ys[i] ); - if ( newdist < dist1 ) - { - dist1 = newdist; - color1 = colors[i]; - } - else if ( newdist < dist2 ) - { - dist2 = newdist; - color2 = colors[i]; - } - } - /* And assign interpolated color. */ - newdist = dist1 + dist2; - r = PPM_GETR(color1)*dist2/newdist + PPM_GETR(color2)*dist1/newdist; - g = PPM_GETG(color1)*dist2/newdist + PPM_GETG(color2)*dist1/newdist; - b = PPM_GETB(color1)*dist2/newdist + PPM_GETB(color2)*dist1/newdist; - PPM_ASSIGN( pixels[row][col], r, g, b ); +static void +assignInterpolatedColor(pixel * const resultP, + pixel const color1, + double const dist1, + pixel const color2, + double const dist2) { + + if (dist1 == 0) + /* pixel is a pole */ + *resultP = color1; + else { + double const sum = dist1 + dist2; + + pixval const r = (PPM_GETR(color1)*dist2 + PPM_GETR(color2)*dist1)/sum; + pixval const g = (PPM_GETG(color1)*dist2 + PPM_GETG(color2)*dist1)/sum; + pixval const b = (PPM_GETB(color1)*dist2 + PPM_GETB(color2)*dist1)/sum; + + PPM_ASSIGN(*resultP, r, g, b); + } +} + + + +static void +poles(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + + unsigned int const poleCt = MAX(2, MIN(MAXPOLES, cols * rows / 30000)); + + int xs[MAXPOLES], ys[MAXPOLES]; + pixel colors[MAXPOLES]; + unsigned int row; + + placeAndColorPolesRandomly(xs, ys, colors, cols, rows, maxval, poleCt); + + /* Interpolate points */ + + for (row = 0; row < rows; ++row) { + unsigned int col; + for (col = 0; col < cols; ++col) { + double dist1, dist2; + pixel color1, color2; + unsigned int i; + + /* Find two closest poles. */ + dist1 = dist2 = (SQR((double)cols) + SQR((double)rows)); + for (i = 0; i < poleCt; ++i) { + double const newdist = + (double)(col - xs[i]) * (col - xs[i]) + + (double)(row - ys[i]) * (row - ys[i]); + if (newdist < dist1) { + dist2 = dist1; + color2 = color1; + dist1 = newdist; + color1 = colors[i]; + } else if (newdist < dist2) { + dist2 = newdist; + color2 = colors[i]; + } + } + assignInterpolatedColor(&pixels[row][col], + color1, dist1, color2, dist2); } } +} + + -/* Squig stuff. */ +/*---------------------------------------------------------------------------- + Squig stuff +-----------------------------------------------------------------------------*/ #define SQUIGS 5 #define SQ_POINTS 7 #define SQ_MAXCIRCLE_POINTS 5000 -static int sq_radius, sq_circlecount; +static int sq_circlecount; static pixel sq_colors[SQ_MAXCIRCLE_POINTS]; -static int sq_xoffs[SQ_MAXCIRCLE_POINTS], sq_yoffs[SQ_MAXCIRCLE_POINTS]; +static ppmd_point sq_offs[SQ_MAXCIRCLE_POINTS]; -static void -sq_measurecircle_drawproc(pixel** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void* const clientdata) -{ - sq_xoffs[sq_circlecount] = col; - sq_yoffs[sq_circlecount] = row; - ++sq_circlecount; + + +static ppmd_point +vectorSum(ppmd_point const a, + ppmd_point const b) { + + return ppmd_makePoint(a.x + b.x, a.y + b.y); } + + +static ppmd_drawprocp sqMeasureCircleDrawproc; + static void -sq_rainbowcircle_drawproc(pixel** const pixels, - int const cols, - int const rows, - pixval const maxval, - int const col, - int const row, - const void* const clientdata ) -{ - int i; +sqMeasureCircleDrawproc(pixel** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + ppmd_point const p, + const void * const clientdata) { + + sq_offs[sq_circlecount++] = p; +} - for ( i = 0; i < sq_circlecount; ++i ) - ppmd_point_drawproc( - pixels, cols, rows, maxval, col + sq_xoffs[i], row + sq_yoffs[i], - &(sq_colors[i]) ); - } +static ppmd_drawprocp sqRainbowCircleDrawproc; static void -sq_assign_colors(int const circlecount, - pixval const maxval, - pixel * const colors) { +sqRainbowCircleDrawproc(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval, + ppmd_point const p, + const void * const clientdata) { - pixel rc1, rc2, rc3; - float cco3; unsigned int i; - rc1 = random_bright_color(maxval); - rc2 = random_bright_color(maxval); - rc3 = random_bright_color(maxval); - cco3 = (circlecount - 1) / 3.0; + for (i = 0; i < sq_circlecount; ++i) + ppmd_point_drawprocp( + pixels, cols, rows, maxval, vectorSum(p, sq_offs[i]), + &sq_colors[i]); +} + + + +static void +sqAssignColors(unsigned int const circlecount, + pixval const maxval, + pixel * const colors) { + + pixel const rc1 = randomBrightColor(maxval); + pixel const rc2 = randomBrightColor(maxval); + pixel const rc3 = randomBrightColor(maxval); + float const cco3 = (circlecount - 1) / 3.0; + + unsigned int i; for (i = 0; i < circlecount ; ++i) { if (i < cco3) { @@ -730,336 +954,219 @@ sq_assign_colors(int const circlecount, } -#if __STDC__ -static void -squig( pixel** pixels, int cols, int rows, pixval maxval ) -#else /*__STDC__*/ + static void -squig( pixels, cols, rows, maxval ) - pixel** pixels; - int cols, rows; - pixval maxval; -#endif /*__STDC__*/ - { +clearImageToBlack(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { + pixel color; - int i, j, xc[SQ_POINTS], yc[SQ_POINTS], x0, y0, x1, y1, x2, y2, x3, y3; - /* Clear image to black. */ - PPM_ASSIGN( color, 0, 0, 0 ); + PPM_ASSIGN(color, 0, 0, 0); + ppmd_filledrectangle( pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color ); + &color); +} - /* Draw the squigs. */ - (void) ppmd_setlinetype( PPMD_LINETYPE_NODIAGS ); - (void) ppmd_setlineclip( 0 ); - for ( i = SQUIGS; i > 0; --i ) - { - /* Measure circle. */ - sq_radius = ( cols + rows ) / 2 / ( 25 + i * 2 ); - sq_circlecount = 0; - ppmd_circle( - pixels, cols, rows, maxval, 0, 0, sq_radius, - sq_measurecircle_drawproc, NULL ); - sq_assign_colors( sq_circlecount, maxval, sq_colors ); - - /* Choose wrap-around point. */ - switch ( rand() % 4 ) - { - case 0: - x1 = rand() % cols; - y1 = 0; - if ( x1 < cols / 2 ) - xc[0] = rand() % ( x1 * 2 + 1); + + +static void +chooseWrapAroundPoint(unsigned int const cols, + unsigned int const rows, + ppmd_point * const pFirstP, + ppmd_point * const pLastP, + ppmd_point * const p0P, + ppmd_point * const p1P, + ppmd_point * const p2P, + ppmd_point * const p3P) { + + switch (rand() % 4) { + case 0: + p1P->x = rand() % cols; + p1P->y = 0; + if (p1P->x < cols / 2) + pFirstP->x = rand() % (p1P->x * 2 + 1); else - xc[0] = cols - 1 - rand() % ( ( cols - x1 ) * 2 ); - yc[0] = rand() % rows; - x2 = x1; - y2 = rows - 1; - xc[SQ_POINTS - 1] = 2 * x2 - xc[0]; - yc[SQ_POINTS - 1] = y2 - yc[0]; - x0 = xc[SQ_POINTS - 1]; - y0 = yc[SQ_POINTS - 1] - rows; - x3 = xc[0]; - y3 = yc[0] + rows; + pFirstP->x = cols - 1 - rand() % ((cols - p1P->x) * 2); + pFirstP->y = rand() % rows; + p2P->x = p1P->x; + p2P->y = rows - 1; + pLastP->x = 2 * p2P->x - pFirstP->x; + pLastP->y = p2P->y - pFirstP->y; + p0P->x = pLastP->x; + p0P->y = pLastP->y - rows; + p3P->x = pFirstP->x; + p3P->y = pFirstP->y + rows; break; - case 1: - x2 = rand() % cols; - y2 = 0; - if ( x2 < cols / 2 ) - xc[SQ_POINTS - 1] = rand() % ( x2 * 2 + 1); + case 1: + p2P->x = rand() % cols; + p2P->y = 0; + if (p2P->x < cols / 2) + pLastP->x = rand() % (p2P->x * 2 + 1); else - xc[SQ_POINTS - 1] = cols - 1 - rand() % ( ( cols - x2 ) * 2 ); - yc[SQ_POINTS - 1] = rand() % rows; - x1 = x2; - y1 = rows - 1; - xc[0] = 2 * x1 - xc[SQ_POINTS - 1]; - yc[0] = y1 - yc[SQ_POINTS - 1]; - x0 = xc[SQ_POINTS - 1]; - y0 = yc[SQ_POINTS - 1] + rows; - x3 = xc[0]; - y3 = yc[0] - rows; + pLastP->x = cols - 1 - rand() % ((cols - p2P->x) * 2); + pLastP->y = rand() % rows; + p1P->x = p2P->x; + p1P->y = rows - 1; + pFirstP->x = 2 * p1P->x - pLastP->x; + pFirstP->y = p1P->y - pLastP->y; + p0P->x = pLastP->x; + p0P->y = pLastP->y + rows; + p3P->x = pFirstP->x; + p3P->y = pFirstP->y - rows; break; - case 2: - x1 = 0; - y1 = rand() % rows; - xc[0] = rand() % cols; - if ( y1 < rows / 2 ) - yc[0] = rand() % ( y1 * 2 + 1); + case 2: + p1P->x = 0; + p1P->y = rand() % rows; + pFirstP->x = rand() % cols; + if (p1P->y < rows / 2) + pFirstP->y = rand() % (p1P->y * 2 + 1); else - yc[0] = rows - 1 - rand() % ( ( rows - y1 ) * 2 ); - x2 = cols - 1; - y2 = y1; - xc[SQ_POINTS - 1] = x2 - xc[0]; - yc[SQ_POINTS - 1] = 2 * y2 - yc[0]; - x0 = xc[SQ_POINTS - 1] - cols; - y0 = yc[SQ_POINTS - 1]; - x3 = xc[0] + cols; - y3 = yc[0]; + pFirstP->y = rows - 1 - rand() % ((rows - p1P->y) * 2); + p2P->x = cols - 1; + p2P->y = p1P->y; + pLastP->x = p2P->x - pFirstP->x; + pLastP->y = 2 * p2P->y - pFirstP->y; + p0P->x = pLastP->x - cols; + p0P->y = pLastP->y; + p3P->x = pFirstP->x + cols; + p3P->y = pFirstP->y; break; - case 3: - x2 = 0; - y2 = rand() % rows; - xc[SQ_POINTS - 1] = rand() % cols; - if ( y2 < rows / 2 ) - yc[SQ_POINTS - 1] = rand() % ( y2 * 2 + 1); + case 3: + p2P->x = 0; + p2P->y = rand() % rows; + pLastP->x = rand() % cols; + if (p2P->y < rows / 2) + pLastP->y = rand() % (p2P->y * 2 + 1); else - yc[SQ_POINTS - 1] = rows - 1 - rand() % ( ( rows - y2 ) * 2 ); - x1 = cols - 1; - y1 = y2; - xc[0] = x1 - xc[SQ_POINTS - 1]; - yc[0] = 2 * y1 - yc[SQ_POINTS - 1]; - x0 = xc[SQ_POINTS - 1] + cols; - y0 = yc[SQ_POINTS - 1]; - x3 = xc[0] - cols; - y3 = yc[0]; + pLastP->y = rows - 1 - rand() % ((rows - p2P->y) * 2); + p1P->x = cols - 1; + p1P->y = p2P->y; + pFirstP->x = p1P->x - pLastP->x; + pFirstP->y = 2 * p1P->y - pLastP->y; + p0P->x = pLastP->x + cols; + p0P->y = pLastP->y; + p3P->x = pFirstP->x - cols; + p3P->y = pFirstP->y; break; - } - - for ( j = 1; j < SQ_POINTS - 1; ++j ) - { - xc[j] = ( rand() % ( cols - 2 * sq_radius ) ) + sq_radius; - yc[j] = ( rand() % ( rows - 2 * sq_radius ) ) + sq_radius; - } - - ppmd_line( - pixels, cols, rows, maxval, x0, y0, x1, y1, - sq_rainbowcircle_drawproc, NULL ); - ppmd_polyspline( - pixels, cols, rows, maxval, x1, y1, SQ_POINTS, xc, yc, x2, y2, - sq_rainbowcircle_drawproc, NULL ); - ppmd_line( - pixels, cols, rows, maxval, x2, y2, x3, y3, - sq_rainbowcircle_drawproc, NULL ); } - } - +} -/* Test pattern. Just a place to put ppmdraw exercises. */ static void -test(pixel ** const pixels, - unsigned int const cols, - unsigned int const rows, - pixval const maxval) { +squig(pixel ** const pixels, + unsigned int const cols, + unsigned int const rows, + pixval const maxval) { - pixel color; - struct fillobj * fh; + int i; + + clearImageToBlack(pixels, cols, rows, maxval); - /* Clear image to black. */ - PPM_ASSIGN( color, 0, 0, 0 ); - ppmd_filledrectangle( - pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, - &color); + /* Draw the squigs. */ + ppmd_setlinetype(PPMD_LINETYPE_NODIAGS); + ppmd_setlineclip(0); + for (i = SQUIGS; i > 0; --i) { + unsigned int const radius = (cols + rows) / 2 / (25 + i * 2); + + ppmd_point c[SQ_POINTS]; + ppmd_point p0, p1, p2, p3; + sq_circlecount = 0; + ppmd_circlep(pixels, cols, rows, maxval, + ppmd_makePoint(0, 0), radius, + sqMeasureCircleDrawproc, NULL); + sqAssignColors(sq_circlecount, maxval, sq_colors); + + chooseWrapAroundPoint(cols, rows, &c[0], &c[SQ_POINTS-1], + &p0, &p1, &p2, &p3); - fh = ppmd_fill_create(); - - ppmd_line(pixels, cols, rows, maxval, - cols/8, rows/8, cols/2, rows/4, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/2, rows/4, cols-cols/8, rows/8, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols-cols/8, rows/8, cols/2, rows/2, ppmd_fill_drawproc, fh); - ppmd_spline3(pixels, cols, rows, maxval, - cols/2, rows/2, cols/2-cols/16, rows/2-rows/10, - cols/2-cols/8, rows/2, ppmd_fill_drawproc, fh); - ppmd_spline3(pixels, cols, rows, maxval, - cols/2-cols/8, rows/2, cols/4+cols/16, rows/2+rows/10, - cols/4, rows/2, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/4, rows/2, cols/8, rows/2, ppmd_fill_drawproc, fh); - ppmd_line(pixels, cols, rows, maxval, - cols/8, rows/2, cols/8, rows/8, ppmd_fill_drawproc, fh); - - PPM_ASSIGN(color, maxval, maxval, maxval); - ppmd_fill(pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color); + { + /* Do the middle points */ + unsigned int j; - ppmd_fill_destroy(fh); + for (j = 1; j < SQ_POINTS - 1; ++j) { + c[j].x = (rand() % (cols - 2 * radius)) + radius; + c[j].y = (rand() % (rows - 2 * radius)) + radius; + } + } + ppmd_linep( + pixels, cols, rows, maxval, p0, p1, + sqRainbowCircleDrawproc, NULL); + ppmd_polysplinep( + pixels, cols, rows, maxval, p1, SQ_POINTS, c, p2, + sqRainbowCircleDrawproc, NULL); + ppmd_linep( + pixels, cols, rows, maxval, p2, p3, + sqRainbowCircleDrawproc, NULL); + } } int -main(int argc, char ** argv) { - - pixel** pixels; - int argn, pattern, cols, rows; -#define PAT_NONE 0 -#define PAT_GINGHAM2 1 -#define PAT_GINGHAM3 2 -#define PAT_MADRAS 3 -#define PAT_TARTAN 4 -#define PAT_POLES 5 -#define PAT_SQUIG 6 -#define PAT_CAMO 7 -#define PAT_ANTICAMO 8 -#define PAT_TEST 9 - const char* const usage = "-gingham2|-g2|-gingham3|-g3|-madras|-tartan|-poles|-squig|-camo|-anticamo <width> <height>"; - - - ppm_init(&argc, argv); - - argn = 1; - pattern = PAT_NONE; - - while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) - { - if ( pm_keymatch( argv[argn], "-gingham2", 9 ) || - pm_keymatch( argv[argn], "-g2", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_GINGHAM2; - } - else if ( pm_keymatch( argv[argn], "-gingham3", 9 ) || - pm_keymatch( argv[argn], "-g3", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_GINGHAM3; - } - else if ( pm_keymatch( argv[argn], "-madras", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_MADRAS; - } - else if ( pm_keymatch( argv[argn], "-tartan", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_TARTAN; - } - else if ( pm_keymatch( argv[argn], "-poles", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_POLES; - } - else if ( pm_keymatch( argv[argn], "-squig", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_SQUIG; - } - else if ( pm_keymatch( argv[argn], "-camo", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_CAMO; - } - else if ( pm_keymatch( argv[argn], "-anticamo", 2 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_ANTICAMO; - } - else if ( pm_keymatch( argv[argn], "-test", 3 ) ) - { - if ( pattern != PAT_NONE ) - pm_error( "only one base pattern may be specified" ); - pattern = PAT_TEST; - } - else - pm_usage( usage ); - ++argn; - } - if ( pattern == PAT_NONE ) - pm_error( "a base pattern must be specified" ); - - if ( argn == argc ) - pm_usage( usage); - if ( sscanf( argv[argn], "%d", &cols ) != 1 ) - pm_usage( usage ); - ++argn; - if ( argn == argc ) - pm_usage( usage); - if ( sscanf( argv[argn], "%d", &rows ) != 1 ) - pm_usage( usage ); - ++argn; - - if ( argn != argc ) - pm_usage( usage); - - if (cols < 1) - pm_error("width must be at least 1"); - if (rows < 1) - pm_error("height must be at least 1"); - - srand( (int) ( time( 0 ) ^ getpid( ) ) ); - pixels = ppm_allocarray( cols, rows ); - - switch ( pattern ) - { +main(int argc, const char ** argv) { + + struct cmdlineInfo cmdline; + pixel ** pixels; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + validateComputableDimensions(cmdline.width, cmdline.height); + + srand(pm_randseed()); + pixels = ppm_allocarray(cmdline.width, cmdline.height); + + switch (cmdline.basePattern) { case PAT_GINGHAM2: - gingham2( pixels, cols, rows, PPM_MAXMAXVAL ); + gingham2(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_GINGHAM3: - gingham3( pixels, cols, rows, PPM_MAXMAXVAL ); + gingham3(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_MADRAS: - madras( pixels, cols, rows, PPM_MAXMAXVAL ); + madras(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_TARTAN: - tartan( pixels, cols, rows, PPM_MAXMAXVAL ); + tartan(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_POLES: - poles( pixels, cols, rows, PPM_MAXMAXVAL ); + poles(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_SQUIG: - squig( pixels, cols, rows, PPM_MAXMAXVAL ); + squig(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); break; case PAT_CAMO: - camo( pixels, cols, rows, PPM_MAXMAXVAL, 0 ); + camo(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL, 0); break; case PAT_ANTICAMO: - camo( pixels, cols, rows, PPM_MAXMAXVAL, 1 ); - break; - - case PAT_TEST: - test( pixels, cols, rows, PPM_MAXMAXVAL ); + camo(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL, 1); break; default: - pm_error( "can't happen!" ); + pm_error("can't happen!"); } - /* All done, write it out. */ - ppm_writeppm( stdout, pixels, cols, rows, PPM_MAXMAXVAL, 0 ); - pm_close( stdout ); + ppm_writeppm(stdout, pixels, cmdline.width, cmdline.height, + PPM_MAXMAXVAL, 0); + + ppm_freearray(pixels, cmdline.height); - exit( 0 ); + return 0; } |