diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2013-06-29 19:19:47 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2013-06-29 19:19:47 +0000 |
commit | 380588e187c12000ac8082cb2a20a905d3c422a5 (patch) | |
tree | 296b1324b7a9360646a34ae836b8eb486b7feede /generator | |
parent | f8b633c2be1231a0c194214271caa456dc669ecb (diff) | |
download | netpbm-mirror-380588e187c12000ac8082cb2a20a905d3c422a5.tar.gz netpbm-mirror-380588e187c12000ac8082cb2a20a905d3c422a5.tar.xz netpbm-mirror-380588e187c12000ac8082cb2a20a905d3c422a5.zip |
Release 10.63.00
git-svn-id: http://svn.code.sf.net/p/netpbm/code/advanced@1968 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'generator')
-rw-r--r-- | generator/pamgauss.c | 2 | ||||
-rw-r--r-- | generator/pamgradient.c | 8 | ||||
-rw-r--r-- | generator/pamseq.c | 2 | ||||
-rw-r--r-- | generator/pgmnoise.c | 97 | ||||
-rw-r--r-- | generator/ppmcie.c | 114 | ||||
-rw-r--r-- | generator/ppmforge.c | 413 | ||||
-rwxr-xr-x | generator/ppmrainbow | 26 |
7 files changed, 369 insertions, 293 deletions
diff --git a/generator/pamgauss.c b/generator/pamgauss.c index b6afdb7e..0e1661e6 100644 --- a/generator/pamgauss.c +++ b/generator/pamgauss.c @@ -9,8 +9,6 @@ #include "mallocvar.h" #include "pam.h" -#define true (1) -#define false (0) struct cmdlineInfo { diff --git a/generator/pamgradient.c b/generator/pamgradient.c index 6546e334..57e78288 100644 --- a/generator/pamgradient.c +++ b/generator/pamgradient.c @@ -18,7 +18,7 @@ struct cmdlineInfo { }; static void -parseCommandLine(int argc, char **argv, +parseCommandLine(int argc, const char **argv, struct cmdlineInfo * const cmdlineP) { /*---------------------------------------------------------------------------- Convert program invocation arguments (argc,argv) into a format the @@ -45,7 +45,7 @@ parseCommandLine(int argc, char **argv, opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (!maxvalSpec) @@ -153,7 +153,7 @@ createEdge(const struct pam * const pamP, int -main(int argc, char *argv[]) { +main(int argc, const char *argv[]) { struct cmdlineInfo cmdline; struct pam pam; @@ -162,7 +162,7 @@ main(int argc, char *argv[]) { tuple * rightEdge; unsigned int row; - pnm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); diff --git a/generator/pamseq.c b/generator/pamseq.c index b1ed0c79..1af5252a 100644 --- a/generator/pamseq.c +++ b/generator/pamseq.c @@ -7,8 +7,6 @@ #include "pam.h" #include "shhopt.h" -#define true (1) -#define false (0) struct cmdlineInfo { diff --git a/generator/pgmnoise.c b/generator/pgmnoise.c index bf73ea48..442edc59 100644 --- a/generator/pgmnoise.c +++ b/generator/pgmnoise.c @@ -7,6 +7,8 @@ #include "mallocvar.h" #include "shhopt.h" #include "pgm.h" +#include <assert.h> + struct cmdlineInfo { @@ -15,13 +17,13 @@ struct cmdlineInfo { */ unsigned int width; unsigned int height; + unsigned int maxval; unsigned int randomseed; unsigned int randomseedSpec; }; - static void parseCommandLine(int argc, const char ** const argv, struct cmdlineInfo * const cmdlineP) { @@ -34,12 +36,15 @@ parseCommandLine(int argc, const char ** const argv, */ optStruct3 opt; unsigned int option_def_index; + unsigned int maxvalSpec; MALLOCARRAY_NOFAIL(option_def, 100); option_def_index = 0; /* incremented by OPTENT3 */ OPTENT3(0, "randomseed", OPT_UINT, &cmdlineP->randomseed, &cmdlineP->randomseedSpec, 0); + OPTENT3(0, "maxval", OPT_UINT, &cmdlineP->maxval, + &maxvalSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -47,6 +52,16 @@ parseCommandLine(int argc, const char ** const argv, pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + free(option_def); + + if (maxvalSpec) { + if (cmdlineP->maxval > PGM_OVERALLMAXVAL) + pm_error("Maxval too large: %u. Maximu is %u", + cmdlineP->maxval, PGM_OVERALLMAXVAL); + else if (cmdlineP->maxval == 0) + pm_error("Maxval must not be zero"); + } else + cmdlineP->maxval = PGM_MAXMAXVAL; if (argc-1 != 2) pm_error("Wrong number of arguments: %u. " @@ -66,30 +81,95 @@ parseCommandLine(int argc, const char ** const argv, else cmdlineP->height = height; } - free(option_def); } +static unsigned int +randPool(unsigned int const digits) { +/*---------------------------------------------------------------------------- + Draw 'digits' bits from pool of random bits. If the number of random bits + in pool is insufficient, call rand() and add 31 bits to it. + + 'digits' must be at most 16. + + We assume that each call to rand() generates 31 bits, or RAND_MAX == + 2147483647. + + The underlying logic is flexible and endian-free. The above conditions + can be relaxed. +-----------------------------------------------------------------------------*/ + static unsigned long int hold=0; /* entropy pool */ + static unsigned int len=0; /* number of valid bits in pool */ + + unsigned int const mask = (1 << digits) - 1; + + unsigned int retval; + + assert(RAND_MAX == 2147483647 && digits <= 16); + + retval = hold; /* initial value */ + + if (len > digits) { /* Enough bits in hold to satisfy request */ + hold >>= digits; + len -= digits; + } else { /* Load another 31 bits into hold */ + hold = rand(); + retval |= (hold << len); + hold >>= (digits - len); + len = 31 - digits + len; + } + return (retval & mask); +} + + static void -pgmnoise(FILE * const ofP, +pgmnoise(FILE * const ofP, unsigned int const cols, unsigned int const rows, gray const maxval) { + bool const usingPool = !(RAND_MAX==2147483647 && (maxval & (maxval+1))); + unsigned int const bitLen = pm_maxvaltobits(maxval); + unsigned int row; gray * destrow; + /* If maxval is 2^n-1, we draw exactly n bits from the pool. + Otherwise call rand() and determine gray value by modulo. + + In the latter case, there is a miniscule skew toward 0 (=black) + because smaller numbers are produced more frequently by modulo. + Thus we employ the pool method only when it is certain that no + skew will ensue. + + To illustrate the point, consider converting the outcome of one + roll of a fair, six-sided die to 5 values (0 to 4) by N % 5. The + probability for values 1, 2, 3, 4 are 1/6, but 0 alone is 2/6. + Average is 10/6 or 1.6667, compared to 2.0 from an ideal + generator which produces exactly 5 values. With two dice + average improves to 70/36 or 1.9444. + + The more (distinct) dice we roll, or the more binary digits we + draw, the smaller the skew. + */ + destrow = pgm_allocrow(cols); pgm_writepgminit(ofP, cols, rows, maxval, 0); for (row = 0; row < rows; ++row) { - unsigned int col; - for (col = 0; col < cols; ++col) - destrow[col] = rand() % (maxval + 1); - + if (usingPool) { + unsigned int col; + for (col = 0; col < cols; ++col) + destrow[col] = randPool(bitLen); + } + else { + unsigned int col; + for (col = 0; col < cols; ++col) + destrow[col] = rand() % (maxval + 1); + } pgm_writepgmrow(ofP, destrow, cols, maxval, 0); } @@ -110,8 +190,7 @@ main(int argc, srand(cmdline.randomseedSpec ? cmdline.randomseed : pm_randseed()); - pgmnoise(stdout, cmdline.width, cmdline.height, PGM_MAXMAXVAL); + pgmnoise(stdout, cmdline.width, cmdline.height, cmdline.maxval); return 0; } - diff --git a/generator/ppmcie.c b/generator/ppmcie.c index 69af5732..717ed13b 100644 --- a/generator/ppmcie.c +++ b/generator/ppmcie.c @@ -35,10 +35,8 @@ #include "nstring.h" #define CLAMP(v, l, h) ((v) < (l) ? (l) : (v) > (h) ? (h) : (v)) -#define TRUE 1 -#define FALSE 0 -#define Maxval 255 /* Maxval to use in generated pixmaps */ +pixval const cieMaxval = 255; /* Maxval to use in generated pixmaps */ /* A color system is defined by the CIE x and y coordinates of its three primary illuminants and the x and y coordinates of the white @@ -522,12 +520,12 @@ makeAllBlack(pixel ** const pixels, static void drawTongueOutline(pixel ** const pixels, - int const pixcols, - int const pixrows, - pixval const maxval, - bool const upvp, - int const xBias, - int const yBias) { + int const pixcols, + int const pixrows, + pixval const maxval, + bool const upvp, + int const xBias, + int const yBias) { int const pxcols = pixcols - xBias; int const pxrows = pixrows - yBias; @@ -546,7 +544,7 @@ drawTongueOutline(pixel ** const pixels, &icx, &icy); if (wavelength > 380) - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly), B(icx, icy), PPMD_NULLDRAWPROC, (char *) &rgbcolor); else { @@ -585,12 +583,12 @@ findTongue(pixel ** const pixels, ++i); if (i >= pxcols) - *presentP = FALSE; + *presentP = false; else { int j; int const leftEdge = i; - *presentP = TRUE; + *presentP = true; for (j = pxcols - 1; j >= leftEdge && PPM_GETR(Bixels(row, j)) == 0; @@ -652,16 +650,16 @@ fillInTongue(pixel ** const pixels, xyz_to_rgb(cs, cx, cy, cz, &jr, &jg, &jb); - mx = Maxval; + mx = maxval; /* Check whether the requested color is within the gamut achievable with the given color system. If not, draw it in a reduced intensity, interpolated by desaturation to the closest within-gamut color. */ - if (constrain_rgb(&jr, &jg, &jb)) { - mx = highlightGamut ? Maxval : ((Maxval + 1) * 3) / 4; - } + if (constrain_rgb(&jr, &jg, &jb)) + mx = highlightGamut ? maxval : ((maxval + 1) * 3) / 4; + /* Scale to max(rgb) = 1. */ jmax = MAX(jr, MAX(jg, jb)); if (jmax > 0) { @@ -959,14 +957,14 @@ plotBlackBodyCurve(pixel ** const pixels, } if (t > 1000) { - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly), B(xb, yb), PPMD_NULLDRAWPROC, (char *) &rgbcolor); /* Draw tick mark every 1000 kelvins */ if ((((int) t) % 1000) == 0) { - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(lx, ly - Sz(2)), B(lx, ly + Sz(2)), PPMD_NULLDRAWPROC, (char *) &rgbcolor); @@ -978,7 +976,7 @@ plotBlackBodyCurve(pixel ** const pixels, char bb[20]; sprintf(bb, "%g", t); - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, B(lx - Sz(12), ly - Sz(4)), Sz(6), 0, bb, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -1057,7 +1055,7 @@ plotMonochromeWavelengths( PPM_ASSIGN(rgbcolor, maxval, maxval, maxval); tx = icx + ((x < 520) ? Sz(-2) : ((x >= 535) ? Sz(2) : 0)); ty = icy + ((x < 520) ? 0 : ((x >= 535) ? Sz(-1) : Sz(-2))); - ppmd_line(pixels, pixcols, pixrows, Maxval, + ppmd_line(pixels, pixcols, pixrows, maxval, B(icx, icy), B(tx, ty), PPMD_NULLDRAWPROC, (char *) &rgbcolor); @@ -1089,13 +1087,13 @@ plotMonochromeWavelengths( } /* gamma correct from linear rgb to nonlinear rgb. */ gamma_correct_rgb(cs, &jr, &jg, &jb); - r = Maxval * jr; - g = Maxval * jg; - b = Maxval * jb; + r = maxval * jr; + g = maxval * jg; + b = maxval * jb; PPM_ASSIGN(rgbcolor, (pixval) r, (pixval) g, (pixval) b); sprintf(wl, "%d", x); - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, B(icx + bx, icy + by), Sz(6), 0, wl, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -1127,7 +1125,7 @@ writeLabel(pixel ** const pixels, cs->xBlue, cs->yBlue, cs->xWhite, cs->yWhite); sysdesc[sizeof(sysdesc)-1] = '\0'; /* for robustness */ - ppmd_text(pixels, pixcols, pixrows, Maxval, + ppmd_text(pixels, pixcols, pixrows, maxval, pixcols / 3, Sz(24), Sz(12), 0, sysdesc, PPMD_NULLDRAWPROC, (char *) &rgbcolor); } @@ -1135,8 +1133,8 @@ writeLabel(pixel ** const pixels, int -main(int argc, - char * argv[]) { +main(int argc, + const char * argv[]) { int argn; const char * const usage = "[-[no]black] [-[no]wpoint] [-[no]label] [-no[axes]] [-full]\n\ @@ -1146,24 +1144,24 @@ main(int argc, [-size <s>] [-xsize|-width <x>] [-ysize|-height <y>]"; const struct colorSystem *cs; - int widspec = FALSE, hgtspec = FALSE; + bool widspec = false, hgtspec = false; unsigned int xBias, yBias; - int upvp = FALSE; /* xy or u'v' color coordinates? */ - int showWhite = TRUE; /* Show white point ? */ - int showBlack = TRUE; /* Show black body curve ? */ - int fullChart = FALSE; /* Fill entire tongue ? */ - int showLabel = TRUE; /* Show labels ? */ - int showAxes = TRUE; /* Plot axes ? */ - - ppm_init(&argc, argv); + bool upvp = false; /* xy or u'v' color coordinates? */ + bool showWhite = true; /* Show white point ? */ + bool showBlack = true; /* Show black body curve ? */ + bool fullChart = false; /* Fill entire tongue ? */ + bool showLabel = true; /* Show labels ? */ + bool showAxes = true; /* Plot axes ? */ + + pm_proginit(&argc, argv); argn = 1; cs = &Rec709system; /* default */ while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') { if (pm_keymatch(argv[argn], "-xy", 2)) { - upvp = FALSE; + upvp = false; } else if (pm_keymatch(argv[argn], "-upvp", 1)) { - upvp = TRUE; + upvp = true; } else if (pm_keymatch(argv[argn], "-xsize", 1) || pm_keymatch(argv[argn], "-width", 2)) { if (widspec) { @@ -1172,7 +1170,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1)) pm_usage(usage); - widspec = TRUE; + widspec = true; } else if (pm_keymatch(argv[argn], "-ysize", 1) || pm_keymatch(argv[argn], "-height", 2)) { if (hgtspec) { @@ -1181,7 +1179,7 @@ main(int argc, argn++; if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) pm_usage(usage); - hgtspec = TRUE; + hgtspec = true; } else if (pm_keymatch(argv[argn], "-size", 2)) { if (hgtspec || widspec) { pm_error("already specified a size/height/ysize"); @@ -1190,7 +1188,7 @@ main(int argc, if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1)) pm_usage(usage); sxsize = sysize; - hgtspec = widspec = TRUE; + hgtspec = widspec = true; } else if (pm_keymatch(argv[argn], "-rec709", 1)) { cs = &Rec709system; } else if (pm_keymatch(argv[argn], "-ntsc", 1)) { @@ -1204,23 +1202,23 @@ main(int argc, } else if (pm_keymatch(argv[argn], "-cie", 1)) { cs = &CIEsystem; } else if (pm_keymatch(argv[argn], "-black", 3)) { - showBlack = TRUE; /* Show black body curve */ + showBlack = true; /* Show black body curve */ } else if (pm_keymatch(argv[argn], "-wpoint", 2)) { - showWhite = TRUE; /* Show white point of color system */ + showWhite = true; /* Show white point of color system */ } else if (pm_keymatch(argv[argn], "-noblack", 3)) { - showBlack = FALSE; /* Don't show black body curve */ + showBlack = false; /* Don't show black body curve */ } else if (pm_keymatch(argv[argn], "-nowpoint", 3)) { - showWhite = FALSE; /* Don't show white point of system */ + showWhite = false; /* Don't show white point of system */ } else if (pm_keymatch(argv[argn], "-label", 1)) { - showLabel = TRUE; /* Show labels. */ + showLabel = true; /* Show labels. */ } else if (pm_keymatch(argv[argn], "-nolabel", 3)) { - showLabel = FALSE; /* Don't show labels */ + showLabel = false; /* Don't show labels */ } else if (pm_keymatch(argv[argn], "-axes", 1)) { - showAxes = TRUE; /* Show axes. */ + showAxes = true; /* Show axes. */ } else if (pm_keymatch(argv[argn], "-noaxes", 3)) { - showAxes = FALSE; /* Don't show axes */ + showAxes = false; /* Don't show axes */ } else if (pm_keymatch(argv[argn], "-full", 1)) { - fullChart = TRUE; /* Fill whole tongue full-intensity */ + fullChart = true; /* Fill whole tongue full-intensity */ } else if (pm_keymatch(argv[argn], "-gamma", 2)) { cs = &Customsystem; argn++; @@ -1289,32 +1287,32 @@ main(int argc, makeAllBlack(pixels, pixcols, pixrows); - drawTongueOutline(pixels, pixcols, pixrows, Maxval, upvp, xBias, yBias); + drawTongueOutline(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); - fillInTongue(pixels, pixcols, pixrows, Maxval, cs, upvp, xBias, yBias, + fillInTongue(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias, fullChart); if (showAxes) - drawAxes(pixels, pixcols, pixrows, Maxval, upvp, xBias, yBias); + drawAxes(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); if (showWhite) - plotWhitePoint(pixels, pixcols, pixrows, Maxval, + plotWhitePoint(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias); if (showBlack) - plotBlackBodyCurve(pixels, pixcols, pixrows, Maxval, + plotBlackBodyCurve(pixels, pixcols, pixrows, cieMaxval, upvp, xBias, yBias); /* Plot wavelengths around periphery of the tongue. */ if (showAxes) - plotMonochromeWavelengths(pixels, pixcols, pixrows, Maxval, + plotMonochromeWavelengths(pixels, pixcols, pixrows, cieMaxval, cs, upvp, xBias, yBias); if (showLabel) - writeLabel(pixels, pixcols, pixrows, Maxval, cs); + writeLabel(pixels, pixcols, pixrows, cieMaxval, cs); - ppm_writeppm(stdout, pixels, pixcols, pixrows, Maxval, FALSE); + ppm_writeppm(stdout, pixels, pixcols, pixrows, cieMaxval, 0); return 0; } diff --git a/generator/ppmforge.c b/generator/ppmforge.c index 189e930c..8ea86429 100644 --- a/generator/ppmforge.c +++ b/generator/ppmforge.c @@ -39,6 +39,7 @@ #include "pm_c_util.h" #include "ppm.h" #include "mallocvar.h" +#include "shhopt.h" static double const hugeVal = 1e50; @@ -74,12 +75,6 @@ static double arand, gaussadd, gaussfac; /* Gaussian random parameters */ static double fracdim; /* Fractal dimension */ static double powscale; /* Power law scaling exponent */ static int meshsize = 256; /* FFT mesh size */ -static unsigned int seedarg; /* Seed specified by user */ -static bool seedspec = FALSE; /* Did the user specify a seed ? */ -static bool clouds = FALSE; /* Just generate clouds */ -static bool stars = FALSE; /* Just generate stars */ -static int screenxsize = 256; /* Screen X size */ -static int screenysize = 256; /* Screen Y size */ static double inclangle, hourangle; /* Star position relative to planet */ static bool inclspec = FALSE; /* No inclination specified yet */ static bool hourspec = FALSE; /* No hour specified yet */ @@ -88,6 +83,166 @@ static double glaciers; /* Glacier level */ static int starfraction; /* Star fraction */ static int starcolor; /* Star color saturation */ + +struct CmdlineInfo { + unsigned int clouds; + unsigned int night; + float dimension; + float hourAngle; + unsigned int hourSpec; + float inclAngle; + unsigned int inclinationSpec; + unsigned int meshSize; + unsigned int meshSpec; + float power; + float glaciers; + float ice; + int saturation; + unsigned int seed; + int stars; + unsigned int starsSpec; + unsigned int width; + unsigned int height; +}; + + + +static void +parseCommandLine(int argc, const char **argv, + struct CmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + 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 + argv[] points to. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to OptParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + + unsigned int dimensionSpec, seedSpec, + meshSpec, powerSpec, glaciersSpec, iceSpec, saturationSpec, + starsSpec, widthSpec, heightSpec; + float hour; + float inclination; + unsigned int mesh; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; + OPTENT3(0, "clouds", OPT_FLAG, NULL, &cmdlineP->clouds, 0); + OPTENT3(0, "night", OPT_FLAG, NULL, &cmdlineP->night, 0); + OPTENT3(0, "dimension", OPT_FLOAT, &cmdlineP->dimension, + &dimensionSpec, 0); + OPTENT3(0, "hour", OPT_FLOAT, &hour, + &cmdlineP->hourSpec, 0); + OPTENT3(0, "inclination", OPT_FLOAT, &inclination, + &cmdlineP->inclinationSpec, 0); + OPTENT3(0, "tilt", OPT_FLOAT, &inclination, + &cmdlineP->inclinationSpec, 0); + OPTENT3(0, "mesh", OPT_UINT, &mesh, + &meshSpec, 0); + OPTENT3(0, "power", OPT_FLOAT, &cmdlineP->power, + &powerSpec, 0); + OPTENT3(0, "glaciers", OPT_FLOAT, &cmdlineP->glaciers, + &glaciersSpec, 0); + OPTENT3(0, "ice", OPT_FLOAT, &cmdlineP->ice, + &iceSpec, 0); + OPTENT3(0, "saturation", OPT_INT, &cmdlineP->saturation, + &saturationSpec, 0); + OPTENT3(0, "seed", OPT_UINT, &cmdlineP->seed, + &seedSpec, 0); + OPTENT3(0, "stars", OPT_INT, &cmdlineP->stars, + &starsSpec, 0); + OPTENT3(0, "width", OPT_UINT, &cmdlineP->width, + &widthSpec, 0); + OPTENT3(0, "xsize", OPT_UINT, &cmdlineP->width, + &widthSpec, 0); + OPTENT3(0, "height", OPT_UINT, &cmdlineP->height, + &heightSpec, 0); + OPTENT3(0, "ysize", OPT_UINT, &cmdlineP->height, + &heightSpec, 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 */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (dimensionSpec) { + if (cmdlineP->dimension <= 0.0) + pm_error("-dimension must be greater than zero. " + "You specified %f", cmdlineP->dimension); + } else + cmdlineP->dimension = cmdlineP->clouds ? 2.15 : 2.4; + + if (cmdlineP->hourSpec) + cmdlineP->hourAngle = (M_PI / 12.0) * (hour + 12.0); + + if (cmdlineP->inclinationSpec) + cmdlineP->inclAngle = (M_PI / 180.0) * inclination; + + if (meshSpec) { + unsigned int i; + if (mesh < 2) + pm_error("-mesh value must be at least 2. " + "You specified %u", mesh); + /* Force FFT mesh to the next larger power of 2. */ + for (i = 2; i < mesh; i <<= 1); + cmdlineP->meshSize = i; + } else + cmdlineP->meshSize = 256; + + if (powerSpec) { + if (cmdlineP->power <= 0.0) + pm_error("-power must be greater than zero. " + "You specified %f", cmdlineP->power); + } else + cmdlineP->power = cmdlineP->clouds ? 0.75 : 1.2; + + if (iceSpec) { + if (cmdlineP->ice <= 0.0) + pm_error("-ice must be greater than zero. " + "You specified %f", cmdlineP->ice); + } else + cmdlineP->ice = 0.4; + + if (glaciersSpec) { + if (cmdlineP->glaciers <= 0.0) + pm_error("-glaciers must be greater than 0. " + "You specified %f", cmdlineP->glaciers); + } else + cmdlineP->glaciers = 0.75; + + if (!starsSpec) + cmdlineP->stars = 100; + + if (!saturationSpec) + cmdlineP->saturation = 125; + + if (!seedSpec) + cmdlineP->seed = pm_randseed(); + + if (!widthSpec) + cmdlineP->width = 256; + + if (!heightSpec) + cmdlineP->height = 256; + + if (argc-1 > 0) + pm_error("There are no non-option arguments. " + "You specified %u", argc-1); + + free(option_def); +} + + /* FOURN -- Multi-dimensional fast Fourier transform Called with arguments: @@ -274,19 +429,6 @@ static void spectralsynth(x, n, h) } -static unsigned int -initseed(void) { - /* Generate initial random seed. */ - - unsigned int i; - - srand(pm_randseed()); - for (i = 0; i < 7; ++i) - rand(); - return rand(); -} - - /* TEMPRGB -- Calculate the relative R, G, and B components for a black body emitting light at a given temperature. @@ -417,7 +559,8 @@ makeCp(float * const a, static void -createPlanetStuff(float * const a, +createPlanetStuff(bool const clouds, + float * const a, unsigned int const n, double ** const uP, double ** const u1P, @@ -456,7 +599,9 @@ createPlanetStuff(float * const a, " -inclination %.0f -hour %d -ice %.2f -glaciers %.2f", (siang * (180.0 / M_PI)), (int) (((shang * (12.0 / M_PI)) + 12 + - (flipped ? 12 : 0)) + 0.5) % 24, icelevel, glaciers); + (flipped ? 12 : 0)) + 0.5) % 24, + icelevel, + glaciers); pm_message(" -stars %d -saturation %d.", starfraction, starcolor); } @@ -531,9 +676,9 @@ generateCloudRow(pixel * const pixels, /* Render the FFT output as clouds. */ - unsigned int j; + unsigned int col; - for (j = 0; j < cols; j++) { + for (col = 0; col < cols; ++col) { double r; pixval w; @@ -542,15 +687,15 @@ generateCloudRow(pixel * const pixels, referenced below does not exist. */ if (t1 > 0.0) - r += t1 * u1[j] * cp[byf + bxf[j]] + - t1 * u[j] * cp[byf + bxc[j]]; + r += t1 * u1[col] * cp[byf + bxf[col]] + + t1 * u[col] * cp[byf + bxc[col]]; if (t > 0.0) - r += t * u1[j] * cp[byc + bxf[j]] + - t * u[j] * cp[byc + bxc[j]]; + r += t * u1[col] * cp[byc + bxf[col]] + + t * u[col] * cp[byc + bxc[col]]; w = (r > 127.0) ? (maxval * ((r - 127.0) / 128.0)) : 0; - PPM_ASSIGN(*(pixels + j), w, w, maxval); + PPM_ASSIGN(pixels[col], w, w, maxval); } } @@ -819,7 +964,7 @@ genplanet(bool const stars, pm_message("%s: -seed %d -dimension %.2f -power %.2f -mesh %d", clouds ? "clouds" : "planet", rseed, fracdim, powscale, meshsize); - createPlanetStuff(a, n, &u, &u1, &bxf, &bxc, &cp, &sunvec, + createPlanetStuff(clouds, a, n, &u, &u1, &bxf, &bxc, &cp, &sunvec, cols, maxval); } @@ -940,19 +1085,14 @@ static bool planet(unsigned int const cols, unsigned int const rows, bool const stars, - bool const clouds) { + bool const clouds, + unsigned int const rseed) { /*---------------------------------------------------------------------------- Make a planet. -----------------------------------------------------------------------------*/ float * a; bool error; - unsigned int rseed; /* Current random seed */ - - if (seedspec) - rseed = seedarg; - else - rseed = initseed(); - + initgauss(rseed); if (stars) { @@ -981,200 +1121,39 @@ planet(unsigned int const cols, - int -main(int argc, char ** argv) { +main(int argc, const char ** argv) { + struct CmdlineInfo cmdline; bool success; - int i; - const char * const usage = "\n\ -[-width|-xsize <x>] [-height|-ysize <y>] [-mesh <n>]\n\ -[-clouds] [-dimension <f>] [-power <f>] [-seed <n>]\n\ -[-hour <f>] [-inclination|-tilt <f>] [-ice <f>] [-glaciers <f>]\n\ -[-night] [-stars <n>] [-saturation <n>]"; - bool dimspec = FALSE, meshspec = FALSE, powerspec = FALSE, - widspec = FALSE, hgtspec = FALSE, icespec = FALSE, - glacspec = FALSE, starspec = FALSE, starcspec = FALSE; - - int cols, rows; /* Dimensions of our output image */ - - ppm_init(&argc, argv); - i = 1; - - while ((i < argc) && (argv[i][0] == '-') && (argv[i][1] != '\0')) { - - if (pm_keymatch(argv[i], "-clouds", 2)) { - clouds = TRUE; - } else if (pm_keymatch(argv[i], "-night", 2)) { - stars = TRUE; - } else if (pm_keymatch(argv[i], "-dimension", 2)) { - if (dimspec) { - pm_error("already specified a dimension"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &fracdim) != 1)) - pm_usage(usage); - if (fracdim <= 0.0) { - pm_error("fractal dimension must be greater than 0"); - } - dimspec = TRUE; - } else if (pm_keymatch(argv[i], "-hour", 3)) { - if (hourspec) { - pm_error("already specified an hour"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &hourangle) != 1)) - pm_usage(usage); - hourangle = (M_PI / 12.0) * (hourangle + 12.0); - hourspec = TRUE; - } else if (pm_keymatch(argv[i], "-inclination", 3) || - pm_keymatch(argv[i], "-tilt", 2)) { - if (inclspec) { - pm_error("already specified an inclination/tilt"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &inclangle) != 1)) - pm_usage(usage); - inclangle = (M_PI / 180.0) * inclangle; - inclspec = TRUE; - } else if (pm_keymatch(argv[i], "-mesh", 2)) { - unsigned int j; - if (meshspec) { - pm_error("already specified a mesh size"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%d", &meshsize) != 1)) - pm_usage(usage); + unsigned int cols, rows; /* Dimensions of our output image */ - if (meshsize < 2) - pm_error("mesh must be at least 2"); + pm_proginit(&argc, argv); - /* Force FFT mesh to the next larger power of 2. */ + parseCommandLine(argc, argv, &cmdline); - for (j = meshsize; (j & 1) == 0; j >>= 1) ; - - if (j != 1) { - for (j = 2; j < meshsize; j <<= 1) ; - meshsize = j; - } - meshspec = TRUE; - } else if (pm_keymatch(argv[i], "-power", 2)) { - if (powerspec) { - pm_error("already specified a power factor"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &powscale) != 1)) - pm_usage(usage); - if (powscale <= 0.0) { - pm_error("power factor must be greater than 0"); - } - powerspec = TRUE; - } else if (pm_keymatch(argv[i], "-ice", 3)) { - if (icespec) { - pm_error("already specified ice cap level"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &icelevel) != 1)) - pm_usage(usage); - if (icelevel <= 0.0) { - pm_error("ice cap level must be greater than 0"); - } - icespec = TRUE; - } else if (pm_keymatch(argv[i], "-glaciers", 2)) { - if (glacspec) { - pm_error("already specified glacier level"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%lf", &glaciers) != 1)) - pm_usage(usage); - if (glaciers <= 0.0) { - pm_error("glacier level must be greater than 0"); - } - glacspec = TRUE; - } else if (pm_keymatch(argv[i], "-stars", 3)) { - if (starspec) { - pm_error("already specified a star fraction"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%d", &starfraction) != 1)) - pm_usage(usage); - starspec = TRUE; - } else if (pm_keymatch(argv[i], "-saturation", 3)) { - if (starcspec) { - pm_error("already specified a star color saturation"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%d", &starcolor) != 1)) - pm_usage(usage); - starcspec = TRUE; - } else if (pm_keymatch(argv[i], "-seed", 3)) { - if (seedspec) { - pm_error("already specified a random seed"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%u", &seedarg) != 1)) - pm_usage(usage); - seedspec = TRUE; - } else if (pm_keymatch(argv[i], "-xsize", 2) || - pm_keymatch(argv[i], "-width", 2)) { - if (widspec) { - pm_error("already specified a width/xsize"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%d", &screenxsize) != 1)) - pm_usage(usage); - widspec = TRUE; - } else if (pm_keymatch(argv[i], "-ysize", 2) || - pm_keymatch(argv[i], "-height", 3)) { - if (hgtspec) { - pm_error("already specified a height/ysize"); - } - i++; - if ((i == argc) || (sscanf(argv[i], "%d", &screenysize) != 1)) - pm_usage(usage); - hgtspec = TRUE; - } else { - pm_usage(usage); - } - i++; - } - - - /* Set defaults when explicit specifications were not given. - - The default fractal dimension and power scale depend upon - whether we are generating a planet or clouds. - */ - - if (!dimspec) { - fracdim = clouds ? 2.15 : 2.4; - } - if (!powerspec) { - powscale = clouds ? 0.75 : 1.2; - } - if (!icespec) { - icelevel = 0.4; - } - if (!glacspec) { - glaciers = 0.75; - } - if (!starspec) { - starfraction = 100; - } - if (!starcspec) { - starcolor = 125; - } + fracdim = cmdline.dimension; + hourspec = cmdline.hourSpec; + hourangle = cmdline.hourAngle; + inclspec = cmdline.inclinationSpec; + inclangle = cmdline.inclAngle; + meshsize = cmdline.meshSize; + powscale = cmdline.power; + icelevel = cmdline.ice; + glaciers = cmdline.glaciers; + starfraction = cmdline.stars; + starcolor = cmdline.saturation; /* Force screen to be at least as wide as it is high. Long, skinny screens cause crashes because picture width is calculated based on height. */ - cols = (MAX(screenysize, screenxsize) + 1) & (~1); - rows = screenysize; + cols = (MAX(cmdline.height, cmdline.width) + 1) & (~1); + rows = cmdline.height; - success = planet(cols, rows, stars, clouds); + success = planet(cols, rows, cmdline.night, cmdline.clouds, cmdline.seed); exit(success ? 0 : 1); } diff --git a/generator/ppmrainbow b/generator/ppmrainbow index 96e304ac..c0568d9b 100755 --- a/generator/ppmrainbow +++ b/generator/ppmrainbow @@ -1,4 +1,28 @@ -#!/usr/bin/perl -wl +#!/bin/sh + +############################################################################## +# This is essentially a Perl program. We exec the Perl interpreter specifying +# this same file as the Perl program and use the -x option to cause the Perl +# interpreter to skip down to the Perl code. The reason we do this instead of +# just making /usr/bin/perl the script interpreter (instead of /bin/sh) is +# that the user may have multiple Perl interpreters and the one he wants to +# use is properly located in the PATH. The user's choice of Perl interpreter +# may be crucial, such as when the user also has a PERL5LIB environment +# variable and it selects modules that work with only a certain main +# interpreter program. +# +# An alternative some people use is to have /usr/bin/env as the script +# interpreter. We don't do that because we think the existence and +# compatibility of /bin/sh is more reliable. +# +# Note that we aren't concerned about efficiency because the user who needs +# high efficiency can use directly the programs that this program invokes. +# +############################################################################## + +exec perl -w -x -S -- "$0" "$@" + +#!/usr/bin/perl use strict; use Getopt::Long; |