From 5444dd409430932c3a7e05558531578dde38d89c Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 3 May 2009 01:20:29 +0000 Subject: cleanup, fix a few bugs git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@911 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- generator/ppmpat.c | 1036 +++++++++++++++++++++++++++++----------------------- 1 file changed, 571 insertions(+), 465 deletions(-) (limited to 'generator/ppmpat.c') diff --git a/generator/ppmpat.c b/generator/ppmpat.c index afefae0e..cfb027bf 100644 --- a/generator/ppmpat.c +++ b/generator/ppmpat.c @@ -14,6 +14,7 @@ #include #include +#include #include "pm_c_util.h" #include "mallocvar.h" @@ -30,8 +31,7 @@ typedef enum { PAT_POLES, PAT_SQUIG, PAT_CAMO, - PAT_ANTICAMO, - PAT_TEST + PAT_ANTICAMO } pattern; struct cmdlineInfo { @@ -67,7 +67,6 @@ parseCommandLine(int argc, const char ** argv, unsigned int squig; unsigned int camo; unsigned int anticamo; - unsigned int test; MALLOCARRAY_NOFAIL(option_def, 100); @@ -82,7 +81,6 @@ parseCommandLine(int argc, const char ** argv, OPTENT3(0, "squig", OPT_FLAG, NULL, &squig, 0); OPTENT3(0, "camo", OPT_FLAG, NULL, &camo, 0); OPTENT3(0, "anticamo", OPT_FLAG, NULL, &anticamo, 0); - OPTENT3(0, "test", OPT_FLAG, NULL, &test, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -99,8 +97,7 @@ parseCommandLine(int argc, const char ** argv, poles + squig + camo + - anticamo + - test; + anticamo; if (basePatternCount < 1) pm_error("You must specify a base pattern option such as -gingham2"); @@ -124,8 +121,6 @@ parseCommandLine(int argc, const char ** argv, cmdlineP->basePattern = PAT_CAMO; else if (anticamo) cmdlineP->basePattern = PAT_ANTICAMO; - else if (test) - cmdlineP->basePattern = PAT_TEST; else assert(false); /* Every possibility is accounted for */ } @@ -135,13 +130,104 @@ parseCommandLine(int argc, const char ** argv, 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 pixel -random_anticamo_color(pixval const maxval) { +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 +randomAnticamoColor(pixval const maxval) { int v1, v2, v3; pixel p; @@ -189,17 +275,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: @@ -241,6 +324,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 @@ -254,6 +377,36 @@ 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, @@ -261,57 +414,32 @@ camo(pixel ** const pixels, 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); } @@ -319,455 +447,447 @@ 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 - -static pixel -random_bright_color( pixval maxval ) - { - pixel p; - - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) <= maxval * DARK_THRESH ); - - return p; - } - -static pixel -random_dark_color( pixval maxval ) - { - pixel p; - - do - { - p = random_color( maxval ); - } - while ( PPM_LUMIN( p ) > maxval * DARK_THRESH ); - - return p; - } +/*---------------------------------------------------------------------------- + Gingham stuff +-----------------------------------------------------------------------------*/ -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); +} + + static void -gingham3( pixel** pixels, int cols, int rows, pixval maxval ) - { - int colso4, rowso4; - pixel backcolor, fore1color, fore2color; +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; - colso4 = cols / 4; - rowso4 = rows / 4; - backcolor = random_dark_color( maxval ); - fore1color = random_bright_color( maxval ); - fore2color = random_bright_color( maxval ); + 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); +} + + static void -madras( pixel** pixels, int cols, int rows, pixval maxval ) - { - 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); +} + + static void -tartan( pixel** pixels, int cols, int rows, pixval maxval ) - { - 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 + + static void -poles( pixel** pixels, int cols, int rows, pixval maxval ) - { - 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, + long const dist1, + pixel const color2, + long const dist2) { + + long const sum = dist1 + dist2; + + pixval const r = PPM_GETR(color1)*dist2/sum + PPM_GETR(color2)*dist1/sum; + pixval const g = PPM_GETG(color1)*dist2/sum + PPM_GETG(color2)*dist1/sum; + pixval const b = PPM_GETB(color1)*dist2/sum + 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 = 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) { + long dist1, dist2; + pixel color1, color2; + unsigned int i; + + /* Find two closest poles. */ + dist1 = dist2 = 2000000000; + for (i = 0; i < poleCt; ++i) { + long const 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]; + } + } + 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) { @@ -805,168 +925,158 @@ sq_assign_colors(int const circlecount, } + static void -squig( pixel** pixels, int cols, int rows, pixval maxval ) - { +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 ); + + +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 ); + 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 ); + 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 ); + 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); + } } @@ -1017,10 +1127,6 @@ main(int argc, const char ** argv) { camo(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL, 1); break; - case PAT_TEST: - test(pixels, cmdline.width, cmdline.height, PPM_MAXMAXVAL); - break; - default: pm_error("can't happen!"); } -- cgit 1.4.1