From decwrl!sun-barr!cs.utexas.edu!uunet!allbery Sun Nov 26 14:26:16 PST 1989 Article 1195 of comp.sources.misc: Path: decwrl!sun-barr!cs.utexas.edu!uunet!allbery From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) Newsgroups: comp.sources.misc Subject: v09i029: PBMPLUS part 13 of 19: ppm.shar3 of 3 Message-ID: <72731@uunet.UU.NET> Date: 26 Nov 89 20:29:57 GMT Sender: allbery@uunet.UU.NET Reply-To: jef@helios.ee.lbl.gov (Jef Poskanzer) Lines: 1600 Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) Posting-number: Volume 9, Issue 29 Submitted-by: jef@helios.ee.lbl.gov (Jef Poskanzer) Archive-name: pbmplus/part13 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # ppm/ppmscale.c # ppm/ppmscale.1 # ppm/ppmshear.c # ppm/ppmshear.1 # ppm/ppmpat.c # This archive created: Wed Nov 22 21:14:00 1989 # By: Jef Poskanzer (Paratheo-Anametamystikhood Of Eris Esoteric, Ada Lovelace Cabal) export PATH; PATH=/bin:$PATH if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmscale.c'" '(8732 characters)' if test -f 'ppm/ppmscale.c' then echo shar: will not over-write existing file "'ppm/ppmscale.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmscale.c' X/* ppmscale.c - read a portable pixmap and scale it X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include "ppm.h" X#ifdef SYSV X#include X#else /*SYSV*/ X#include X#endif /*SYSV*/ X X#define SCALE 4096 X#define HALFSCALE 2048 X X#define max(a,b) ((a) > (b) ? (a) : (b)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X pixel *pixelrow, *temppixelrow, *newpixelrow; X register pixel *pP, *npP; X int argn, specxscale, specyscale, specxsize, specysize; X int rows, cols, rowsread, format, newrows, newcols; X register int row, col, needtoreadrow; X pixval maxval; X float xscale, yscale; X long sxscale, syscale; X register long fracrowtofill, fracrowleft; X long *rs, *gs, *bs; X char *usage = " [ppmfile]\n -xsize|width|-ysize|-height [ppmfile]\n -xscale|-yscale [ppmfile]\n -xscale|-xsize|-width -yscale|-ysize|-height [ppmfile]"; X X pm_progname = argv[0]; X X argn = 1; X specxscale = specyscale = specxsize = specysize = 0; X X while ( argn + 1 < argc && argv[argn][0] == '-' ) X { X if ( strncmp(argv[argn],"-xscale",max(strlen(argv[argn]),4)) == 0 ) X { X if ( specxsize ) X pm_error( X "only one of -xsize/-width and -xscale may be specified", X 0,0,0,0,0 ); X if ( sscanf( argv[argn+1], "%g", &xscale ) != 1 ) X pm_usage( usage ); X if ( xscale <= 0.0 ) X pm_error( "x scale must be greater than 0", 0,0,0,0,0 ); X specxscale = 1; X } X else if ( strncmp(argv[argn],"-yscale",max(strlen(argv[argn]),4)) == 0 ) X { X if ( specysize ) X pm_error( X "only one of -ysize/-height and -yscale may be specified", X 0,0,0,0,0 ); X if ( sscanf( argv[argn+1], "%g", &yscale ) != 1 ) X pm_usage( usage ); X if ( yscale <= 0.0 ) X pm_error( "y scale must be greater than 0", 0,0,0,0,0 ); X specyscale = 1; X } X else if ( strncmp(argv[argn],"-xsize",max(strlen(argv[argn]),4)) == 0 || X strncmp(argv[argn],"-width",max(strlen(argv[argn]),2)) == 0 ) X { X if ( specxscale ) X pm_error( X "only one of -xscale and -xsize/-width may be specified", X 0,0,0,0,0 ); X if ( sscanf( argv[argn+1], "%d", &newcols ) != 1 ) X pm_usage( usage ); X if ( newcols <= 0 ) X pm_error( "new width must be greater than 0", 0,0,0,0,0 ); X specxsize = 1; X } X else if ( strncmp(argv[argn],"-ysize",max(strlen(argv[argn]),4)) == 0 || X strncmp(argv[argn],"-height",max(strlen(argv[argn]),2)) == 0 ) X { X if ( specyscale ) X pm_error( X "only one of -yscale and -ysize/-height may be specified", X 0,0,0,0,0 ); X if ( sscanf( argv[argn+1], "%d", &newrows ) != 1 ) X pm_usage( usage ); X if ( newrows <= 0 ) X pm_error( "new height must be greater than 0", 0,0,0,0,0 ); X specysize = 1; X } X else X pm_usage( usage ); X argn += 2; X } X X if ( ! ( specxscale || specyscale || specxsize || specysize ) ) X { X /* No flags specified, so a single scale factor is required. */ X if ( argn == argc ) X pm_usage( usage ); X if ( sscanf( argv[argn], "%g", &xscale ) != 1 ) X pm_usage( usage ); X if ( xscale <= 0.0 ) X pm_error( "scale must be greater than 0", 0,0,0,0,0 ); X argn++; X yscale = xscale; X specxscale = specyscale = 1; X } X X /* Now get input file. */ X if ( argn != argc ) X { X ifd = pm_openr( argv[argn] ); X argn++; X } X else X ifd = stdin; X X if ( argn != argc ) X pm_usage( usage ); X X ppm_pbmmaxval = 255; /* use larger value for better results */ X ppm_readppminit( ifd, &cols, &rows, &maxval, &format ); X X /* Compute all sizes and scales. */ X if ( specxsize ) X xscale = (float) newcols / (float) cols; X else if ( specxscale ) X newcols = cols * xscale + 0.999; X X if ( specysize ) X yscale = (float) newrows / (float) rows; X else if ( specyscale ) X newrows = rows * yscale + 0.999; X else X if ( specxsize ) X { X yscale = xscale; X newrows = rows * yscale + 0.999; X } X else X { X yscale = 1.0; X newrows = rows; X } X X if ( ! ( specxsize || specxscale ) ) X if ( specysize ) X { X xscale = yscale; X newcols = cols * xscale + 0.999; X } X else X { X xscale = 1.0; X newcols = cols; X } X X sxscale = xscale * SCALE; X syscale = yscale * SCALE; X X pixelrow = ppm_allocrow( cols ); X if ( newrows == rows ) /* shortcut Y scaling if possible */ X temppixelrow = pixelrow; X else X temppixelrow = ppm_allocrow( cols ); X rs = (long *) pm_allocrow( cols, sizeof(long) ); X gs = (long *) pm_allocrow( cols, sizeof(long) ); X bs = (long *) pm_allocrow( cols, sizeof(long) ); X rowsread = 0; X fracrowleft = syscale; X needtoreadrow = 1; X for ( col = 0; col < cols; col++ ) X rs[col] = gs[col] = bs[col] = HALFSCALE; X fracrowtofill = SCALE; X X ppm_writeppminit( stdout, newcols, newrows, maxval ); X newpixelrow = ppm_allocrow( newcols ); X X for ( row = 0; row < newrows; row++ ) X { X /* First scale Y from pixelrow into temppixelrow. */ X if ( newrows == rows ) /* shortcut Y scaling if possible */ X { X ppm_readppmrow( ifd, pixelrow, cols, maxval, format ); X } X else X { X while ( fracrowleft < fracrowtofill ) X { X if ( needtoreadrow ) X if ( rowsread < rows ) X { X ppm_readppmrow( ifd, pixelrow, cols, maxval, format ); X rowsread++; X /* needtoreadrow = 0; */ X } X for ( col = 0, pP = pixelrow; col < cols; col++, pP++ ) X { X rs[col] += fracrowleft * PPM_GETR( *pP ); X gs[col] += fracrowleft * PPM_GETG( *pP ); X bs[col] += fracrowleft * PPM_GETB( *pP ); X } X fracrowtofill -= fracrowleft; X fracrowleft = syscale; X needtoreadrow = 1; X } X /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */ X if ( needtoreadrow ) X if ( rowsread < rows ) X { X ppm_readppmrow( ifd, pixelrow, cols, maxval, format ); X rowsread++; X needtoreadrow = 0; X } X for ( col = 0, pP = pixelrow, npP = temppixelrow; X col < cols; col++, pP++, npP++ ) X { X register long r, g, b; X X r = rs[col] + fracrowtofill * PPM_GETR( *pP ); X g = gs[col] + fracrowtofill * PPM_GETG( *pP ); X b = bs[col] + fracrowtofill * PPM_GETB( *pP ); X r /= SCALE; X if ( r > maxval ) r = maxval; X g /= SCALE; X if ( g > maxval ) g = maxval; X b /= SCALE; X if ( b > maxval ) b = maxval; X PPM_ASSIGN( *npP, r, g, b ); X rs[col] = gs[col] = bs[col] = HALFSCALE; X } X fracrowleft -= fracrowtofill; X if ( fracrowleft == 0 ) X { X fracrowleft = syscale; X needtoreadrow = 1; X } X fracrowtofill = SCALE; X } X X /* Now scale X from temppixelrow into newpixelrow and write it out. */ X if ( newcols == cols ) /* shortcut X scaling if possible */ X ppm_writeppmrow( stdout, temppixelrow, newcols, maxval ); X else X { X register long r, g, b; X register long fraccoltofill, fraccolleft; X register int needcol; X X npP = newpixelrow; X fraccoltofill = SCALE; X r = g = b = HALFSCALE; X needcol = 0; X for ( col = 0, pP = temppixelrow; col < cols; col++, pP++ ) X { X fraccolleft = sxscale; X while ( fraccolleft >= fraccoltofill ) X { X if ( needcol ) X { X npP++; X r = g = b = HALFSCALE; X needcol = 0; X } X r += fraccoltofill * PPM_GETR( *pP ); X g += fraccoltofill * PPM_GETG( *pP ); X b += fraccoltofill * PPM_GETB( *pP ); X r /= SCALE; X if ( r > maxval ) r = maxval; X g /= SCALE; X if ( g > maxval ) g = maxval; X b /= SCALE; X if ( b > maxval ) b = maxval; X PPM_ASSIGN( *npP, r, g, b ); X fraccolleft -= fraccoltofill; X fraccoltofill = SCALE; X needcol = 1; X } X if ( fraccolleft > 0 ) X { X if ( needcol ) X { X npP++; X r = g = b = HALFSCALE; X needcol = 0; X } X r += fraccolleft * PPM_GETR( *pP ); X g += fraccolleft * PPM_GETG( *pP ); X b += fraccolleft * PPM_GETB( *pP ); X fraccoltofill -= fraccolleft; X } X } X if ( fraccoltofill > 0 ) X { X pP--; X r += fraccoltofill * PPM_GETR( *pP ); X g += fraccoltofill * PPM_GETG( *pP ); X b += fraccoltofill * PPM_GETB( *pP ); X } X if ( ! needcol ) X { X r /= SCALE; X if ( r > maxval ) r = maxval; X g /= SCALE; X if ( g > maxval ) g = maxval; X b /= SCALE; X if ( b > maxval ) b = maxval; X PPM_ASSIGN( *npP, r, g, b ); X } X ppm_writeppmrow( stdout, newpixelrow, newcols, maxval ); X } X } X X pm_close( ifd ); X X exit( 0 ); X } SHAR_EOF if test 8732 -ne "`wc -c < 'ppm/ppmscale.c'`" then echo shar: error transmitting "'ppm/ppmscale.c'" '(should have been 8732 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmscale.1'" '(1309 characters)' if test -f 'ppm/ppmscale.1' then echo shar: will not over-write existing file "'ppm/ppmscale.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmscale.1' X.TH ppmscale 1 "01 August 1989" X.SH NAME Xppmscale - scale a portable pixmap X.SH SYNOPSIS X.nf Xppmscale [ppmfile] Xppmscale -xsize|-width|-ysize|-height [ppmfile] Xppmscale -xscale|-yscale [ppmfile] Xppmscale -xscale|-xsize|-width -yscale|-ysize|-height [ppmfile] X.fi X.SH DESCRIPTION XReads a portable pixmap as input. XScales it by the specified factor or factors and produces a portable Xpixmap as output. XYou can both enlarge (scale factor > 1) and reduce (scale factor < 1). XYou can specify one dimension as a pixel size, and the other dimension Xwill be scaled correspondingly. XYou can specify one dimension as a scale, and the other dimension Xwill not be scaled. XOr, you can specify different scales for each axis, either as scale Xfactors or as pixel sizes. X.PP XAll flags can be abbreviated to their shortest unique prefix. X.SH "SEE ALSO" Xpbmreduce(1), pnmenlarge(1), ppm(5) X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 1309 -ne "`wc -c < 'ppm/ppmscale.1'`" then echo shar: error transmitting "'ppm/ppmscale.1'" '(should have been 1309 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmshear.c'" '(3120 characters)' if test -f 'ppm/ppmshear.c' then echo shar: will not over-write existing file "'ppm/ppmshear.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmshear.c' X/* ppmshear.c - read a portable pixmap and shear it by some angle X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include X#define M_PI 3.14159265358979323846 X#include "ppm.h" X X#define SCALE 4096 X#define HALFSCALE 2048 X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X FILE *ifd; X pixel **pixels; X register pixel *newpixelrow, *pP, *npP; X pixel bgpixel, prevpixel; X int argn, rows, cols, newcols, row, col; X pixval maxval; X float fangle, shearfac, new0; X int intnew0; X register long fracnew0, omfracnew0; X char *usage = " [ppmfile]"; X X pm_progname = argv[0]; X X argn = 1; X X if ( argn == argc ) X pm_usage( usage ); X if ( sscanf( argv[argn], "%g", &fangle ) != 1 ) X pm_usage( usage ); X argn++; X if ( fangle <= -90.0 || fangle >= 90.0 ) X pm_error( "angle must be between -90 and 90", 0,0,0,0,0 ); X fangle = fangle * M_PI / 180.0; /* convert to radians */ X shearfac = tan( fangle ); X if ( shearfac < 0.0 ) X shearfac = -shearfac; X X if ( argn != argc ) X { X ifd = pm_openr( argv[argn] ); X argn++; X } X else X ifd = stdin; X X if ( argn != argc ) X pm_usage( usage ); X X ppm_pbmmaxval = 255; /* use larger value for better results */ X pixels = ppm_readppm( ifd, &cols, &rows, &maxval ); X X pm_close( ifd ); X X newcols = rows * shearfac + cols + 0.999999; X X ppm_writeppminit( stdout, newcols, rows, maxval ); X newpixelrow = ppm_allocrow( newcols ); X X bgpixel = ppm_backgroundpixel( pixels, cols, rows ); X X for ( row = 0; row < rows; row++ ) X { X if ( fangle > 0.0 ) X new0 = row * shearfac; X else X new0 = ( rows - row ) * shearfac; X intnew0 = (int) new0; X fracnew0 = ( new0 - intnew0 ) * SCALE; X omfracnew0 = SCALE - fracnew0; X X for ( col = 0, npP = newpixelrow; col < newcols; col++, npP++ ) X *npP = bgpixel; X X prevpixel = bgpixel; X X for ( col = 0, npP = &(newpixelrow[intnew0]), pP = pixels[row]; col < cols; col++, npP++, pP++ ) X { X PPM_ASSIGN( *npP, X ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(*pP) + HALFSCALE ) / SCALE, X ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(*pP) + HALFSCALE ) / SCALE, X ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(*pP) + HALFSCALE ) / SCALE ); X prevpixel = *pP; X } X if ( fracnew0 > 0 ) X { X npP = &(newpixelrow[intnew0 + cols]); X PPM_ASSIGN( *npP, X ( fracnew0 * PPM_GETR(prevpixel) + omfracnew0 * PPM_GETR(bgpixel) + HALFSCALE ) / SCALE, X ( fracnew0 * PPM_GETG(prevpixel) + omfracnew0 * PPM_GETG(bgpixel) + HALFSCALE ) / SCALE, X ( fracnew0 * PPM_GETB(prevpixel) + omfracnew0 * PPM_GETB(bgpixel) + HALFSCALE ) / SCALE ); X } X X ppm_writeppmrow( stdout, newpixelrow, newcols, maxval ); X } X X exit( 0 ); X } SHAR_EOF if test 3120 -ne "`wc -c < 'ppm/ppmshear.c'`" then echo shar: error transmitting "'ppm/ppmshear.c'" '(should have been 3120 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmshear.1'" '(1354 characters)' if test -f 'ppm/ppmshear.1' then echo shar: will not over-write existing file "'ppm/ppmshear.1'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmshear.1' X.TH ppmshear 1 "08 February 1989" X.SH NAME Xppmshear - shear a portable pixmap by some angle X.SH SYNOPSIS Xppmshear angle [ppmfile] X.SH DESCRIPTION XReads a portable pixmap as input. XShears it by the specified angle and produces a portable Xpixmap as output. XThe angle is in degrees (floating point), and measures this: X.PP X.nf X +-------+ +-------+ X | | |\\ \\ X | OLD | | \\ NEW \\ X | | |an\\ \\ X +-------+ |gle+-------+ X.fi X.PP XIf the angle is negative, it shears the other way: X.PP X.nf X +-------+ |-an+-------+ X | | |gl/ / X | OLD | |e/ NEW / X | | |/ / X +-------+ +-------+ X.fi X.PP XThe angle should not get too close to 90 or -90, or the resulting Xpixmap will be unreasonably wide. X.PP XThe shearing is implemented by looping over the source pixels and distributing Xfractions to each of the destination pixels. X.SH "SEE ALSO" Xpnmflip(1), ppm(5) X.SH AUTHOR XCopyright (C) 1989 by Jef Poskanzer. X XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. SHAR_EOF if test 1354 -ne "`wc -c < 'ppm/ppmshear.1'`" then echo shar: error transmitting "'ppm/ppmshear.1'" '(should have been 1354 characters)' fi fi # end of overwriting check if test ! -d 'ppm' then echo shar: creating directory "'ppm'" mkdir 'ppm' fi echo shar: extracting "'ppm/ppmpat.c'" '(27285 characters)' if test -f 'ppm/ppmpat.c' then echo shar: will not over-write existing file "'ppm/ppmpat.c'" else sed 's/^X//' << \SHAR_EOF > 'ppm/ppmpat.c' X/* ppmpat.c - make a pixmap X** X** Copyright (C) 1989 by Jef Poskanzer. X** X** Permission to use, copy, modify, and distribute this software and its X** documentation for any purpose and without fee is hereby granted, provided X** that the above copyright notice appear in all copies and that both that X** copyright notice and this permission notice appear in supporting X** documentation. This software is provided "as is" without express or X** implied warranty. X*/ X X#include X#include X#define M_PI 3.14159265358979323846 X#include "ppm.h" X#include "ppmdraw.h" X#ifdef SYSV X#include X#define srandom srand X#define random rand X#else /*SYSV*/ X#include X#endif /*SYSV*/ X X#define max(a,b) ((a) > (b) ? (a) : (b)) X Xmain( argc, argv ) Xint argc; Xchar *argv[]; X { X pixel **pixels; X int argn, pattern, cols, rows; X#define PAT_NONE 0 X#define PAT_GINGHAM2 1 X#define PAT_GINGHAM3 2 X#define PAT_MADRAS 3 X#define PAT_TARTAN 4 X#define PAT_POLES 5 X#define PAT_SQUIG 6 X#define PAT_CAMO 7 X#define PAT_ANTICAMO 8 X#define PAT_TEST 9 X char *usage = "-gingham|-g2|-gingham3|-g3|-madras|-tartan|-poles|-squig|-camo|-anticamo "; X X pm_progname = argv[0]; X X argn = 1; X pattern = PAT_NONE; X X while ( argn < argc && argv[argn][0] == '-' ) X { X if ( strncmp(argv[argn],"-gingham2",max(strlen(argv[argn]),9)) == 0 || X strncmp(argv[argn],"-g2",max(strlen(argv[argn]),3)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_GINGHAM2; X } X else if ( strncmp(argv[argn],"-gingham3",max(strlen(argv[argn]),9)) == 0 || X strncmp(argv[argn],"-g3",max(strlen(argv[argn]),3)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_GINGHAM3; X } X else if ( strncmp(argv[argn],"-madras",max(strlen(argv[argn]),2)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_MADRAS; X } X else if ( strncmp(argv[argn],"-tartan",max(strlen(argv[argn]),2)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_TARTAN; X } X else if ( strncmp(argv[argn],"-poles",max(strlen(argv[argn]),2)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_POLES; X } X else if ( strncmp(argv[argn],"-squig",max(strlen(argv[argn]),2)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_SQUIG; X } X else if ( strncmp(argv[argn],"-camo",max(strlen(argv[argn]),2)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_CAMO; X } X else if (strncmp(argv[argn],"-anticamo",max(strlen(argv[argn]),2)) == 0) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_ANTICAMO; X } X else if ( strncmp(argv[argn],"-test",max(strlen(argv[argn]),3)) == 0 ) X { X if ( pattern != PAT_NONE ) X pm_error( "only one base pattern may be specified", 0,0,0,0,0 ); X pattern = PAT_TEST; X } X else X pm_usage( usage ); X argn++; X } X if ( pattern == PAT_NONE ) X pm_error( "a base pattern must be specified", 0,0,0,0,0 ); X X if ( argn == argc ) X pm_usage( usage); X if ( sscanf( argv[argn], "%d", &cols ) != 1 ) X pm_usage( usage ); X argn++; X if ( argn == argc ) X pm_usage( usage); X if ( sscanf( argv[argn], "%d", &rows ) != 1 ) X pm_usage( usage ); X argn++; X X if ( argn != argc ) X pm_usage( usage); X X srandom( (int) time( 0 ) ); X pixels = ppm_allocarray( cols, rows ); X X switch ( pattern ) X { X case PAT_GINGHAM2: X gingham2( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_GINGHAM3: X gingham3( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_MADRAS: X madras( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_TARTAN: X tartan( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_POLES: X poles( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_SQUIG: X squig( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X case PAT_CAMO: X camo( pixels, cols, rows, PPM_MAXMAXVAL, 0 ); X break; X X case PAT_ANTICAMO: X camo( pixels, cols, rows, PPM_MAXMAXVAL, 1 ); X break; X X case PAT_TEST: X test( pixels, cols, rows, PPM_MAXMAXVAL ); X break; X X default: X pm_error( "can't happen!", 0,0,0,0,0 ); X } X X /* All done, write it out. */ X ppm_writeppm( stdout, pixels, cols, rows, PPM_MAXMAXVAL ); X X exit( 0 ); X } X Xpixel Xrandom_color( maxval ) Xpixval maxval; X { X pixel p; X X PPM_ASSIGN( X p, random() % ( maxval + 1 ), random() % ( maxval + 1 ), X random() % ( maxval + 1 ) ); X X return p; X } X X#define DARK_THRESH 0.25 X Xpixel Xrandom_bright_color( maxval ) Xpixval maxval; X { X pixel p; X X do X { X p = random_color( maxval ); X } X while ( PPM_LUMIN( p ) <= maxval * DARK_THRESH ); X X return p; X } X Xpixel Xrandom_dark_color( maxval ) Xpixval maxval; X { X pixel p; X X do X { X p = random_color( maxval ); X } X while ( PPM_LUMIN( p ) > maxval * DARK_THRESH ); X X return p; X } X Xpixel Xaverage_two_colors( p1, p2 ) Xpixel p1, p2; X { X pixel p; X X PPM_ASSIGN( X p, ( (int) PPM_GETR(p1) + (int) PPM_GETR(p2) ) / 2, X ( (int) PPM_GETG(p1) + (int) PPM_GETG(p2) ) / 2, X ( (int) PPM_GETB(p1) + (int) PPM_GETB(p2) ) / 2 ); X X return p; X } X Xvoid Xaverage_drawproc( pixels, cols, rows, maxval, col, row, clientdata ) Xpixel **pixels; Xint cols, rows, col, row; Xpixval maxval; Xchar *clientdata; X { X if ( col >= 0 && col < cols && row >= 0 && row < rows ) X pixels[row][col] = X average_two_colors( pixels[row][col], *( (pixel *) clientdata ) ); X } X X/* Gingham stuff. */ X Xgingham2( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X int colso2, rowso2; X pixel backcolor, forecolor; X X colso2 = cols / 2; X rowso2 = rows / 2; X backcolor = random_dark_color( maxval ); X forecolor = random_bright_color( maxval ); X X /* Warp. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, colso2, rows, PPMD_NULLDRAWPROC, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, colso2, 0, cols - colso2, rows, X PPMD_NULLDRAWPROC, &forecolor ); X X /* Woof. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rowso2, average_drawproc, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rowso2, cols, rows - rowso2, X average_drawproc, &forecolor ); X } X Xgingham3( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X int colso4, rowso4; X pixel backcolor, fore1color, fore2color; X X colso4 = cols / 4; X rowso4 = rows / 4; X backcolor = random_dark_color( maxval ); X fore1color = random_bright_color( maxval ); X fore2color = random_bright_color( maxval ); X X /* Warp. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, colso4, rows, PPMD_NULLDRAWPROC, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, colso4, 0, colso4, rows, PPMD_NULLDRAWPROC, X &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 2 * colso4, 0, colso4, rows, X PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 3 * colso4, 0, cols - colso4, rows, X PPMD_NULLDRAWPROC, &fore1color ); X X /* Woof. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rowso4, average_drawproc, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rowso4, cols, rowso4, average_drawproc, X &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 2 * rowso4, cols, rowso4, X average_drawproc, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 3 * rowso4, cols, rows - rowso4, X average_drawproc, &fore1color ); X } X Xmadras( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X int cols2, rows2, cols3, rows3, cols12, rows12, cols6a, rows6a, cols6b, X rows6b; X pixel backcolor, fore1color, fore2color; X X cols2 = cols * 2 / 44; X rows2 = rows * 2 / 44; X cols3 = cols * 3 / 44; X rows3 = rows * 3 / 44; X cols12 = cols - 10 * cols2 - 4 * cols3; X rows12 = rows - 10 * rows2 - 4 * rows3; X cols6a = cols12 / 2; X rows6a = rows12 / 2; X cols6b = cols12 - cols6a; X rows6b = rows12 - rows6a; X backcolor = random_dark_color( maxval ); X fore1color = random_bright_color( maxval ); X fore2color = random_bright_color( maxval ); X X /* Warp. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols2, rows, PPMD_NULLDRAWPROC, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols2, 0, cols3, rows, PPMD_NULLDRAWPROC, X &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols2 + cols3, 0, cols2, rows, X PPMD_NULLDRAWPROC, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 2 * cols2 + cols3, 0, cols2, rows, X PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 3 * cols2 + cols3, 0, cols2, rows, X PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 4 * cols2 + cols3, 0, cols6a, rows, X PPMD_NULLDRAWPROC, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 4 * cols2 + cols3 + cols6a, 0, cols2, rows, X PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 5 * cols2 + cols3 + cols6a, 0, cols3, rows, X PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 5 * cols2 + 2 * cols3 + cols6a, 0, cols2, X rows, PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 6 * cols2 + 2 * cols3 + cols6a, 0, cols3, X rows, PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 6 * cols2 + 3 * cols3 + cols6a, 0, cols2, X rows, PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a, 0, cols6b, X rows, PPMD_NULLDRAWPROC, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 7 * cols2 + 3 * cols3 + cols6a + cols6b, 0, X cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 8 * cols2 + 3 * cols3 + cols6a + cols6b, 0, X cols2, rows, PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 9 * cols2 + 3 * cols3 + cols6a + cols6b, 0, X cols2, rows, PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 10 * cols2 + 3 * cols3 + cols6a + cols6b, 0, X cols3, rows, PPMD_NULLDRAWPROC, &fore1color ); X X /* Woof. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rows2, average_drawproc, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows2, cols, rows3, average_drawproc, X &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows2 + rows3, cols, rows2, X average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 2 * rows2 + rows3, cols, rows2, X average_drawproc, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 3 * rows2 + rows3, cols, rows2, X average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 4 * rows2 + rows3, cols, rows6a, X average_drawproc, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 4 * rows2 + rows3 + rows6a, cols, rows2, X average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 5 * rows2 + rows3 + rows6a, cols, rows3, X average_drawproc, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 5 * rows2 + 2 * rows3 + rows6a, cols, X rows2, average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 6 * rows2 + 2 * rows3 + rows6a, cols, X rows3, average_drawproc, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 6 * rows2 + 3 * rows3 + rows6a, cols, X rows2, average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a, cols, X rows6b, average_drawproc, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 7 * rows2 + 3 * rows3 + rows6a + rows6b, X cols, rows2, average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 8 * rows2 + 3 * rows3 + rows6a + rows6b, X cols, rows2, average_drawproc, &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 9 * rows2 + 3 * rows3 + rows6a + rows6b, X cols, rows2, average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 10 * rows2 + 3 * rows3 + rows6a + rows6b, X cols, rows3, average_drawproc, &fore2color ); X } X Xtartan( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X int cols1, rows1, cols3, rows3, cols10, rows10, cols5a, rows5a, cols5b, X rows5b; X pixel backcolor, fore1color, fore2color; X X cols1 = cols / 22; X rows1 = rows / 22; X cols3 = cols * 3 / 22; X rows3 = rows * 3 / 22; X cols10 = cols - 3 * cols1 - 3 * cols3; X rows10 = rows - 3 * rows1 - 3 * rows3; X cols5a = cols10 / 2; X rows5a = rows10 / 2; X cols5b = cols10 - cols5a; X rows5b = rows10 - rows5a; X backcolor = random_dark_color( maxval ); X fore1color = random_bright_color( maxval ); X fore2color = random_bright_color( maxval ); X X /* Warp. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols5a, rows, PPMD_NULLDRAWPROC, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols5a, 0, cols1, rows, PPMD_NULLDRAWPROC, X &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols5a + cols1, 0, cols5b, rows, X PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols10 + cols1, 0, cols3, rows, X PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols10 + cols1 + cols3, 0, cols1, rows, X PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols10 + 2 * cols1 + cols3, 0, cols3, rows, X PPMD_NULLDRAWPROC, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols10 + 2 * cols1 + 2 * cols3, 0, cols1, X rows, PPMD_NULLDRAWPROC, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, cols10 + 3 * cols1 + 2 * cols3, 0, cols3, X rows, PPMD_NULLDRAWPROC, &fore2color ); X X /* Woof. */ X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rows5a, average_drawproc, X &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows5a, cols, rows1, average_drawproc, X &fore1color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows5a + rows1, cols, rows5b, X average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows10 + rows1, cols, rows3, X average_drawproc, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows10 + rows1 + rows3, cols, rows1, X average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + rows3, cols, rows3, X average_drawproc, &fore2color ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows10 + 2 * rows1 + 2 * rows3, cols, X rows1, average_drawproc, &backcolor ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, rows10 + 3 * rows1 + 2 * rows3, cols, X rows3, average_drawproc, &fore2color ); X } X X/* Poles stuff. */ X X#define MAXPOLES 500 X Xpoles( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X int poles, i, xs[MAXPOLES], ys[MAXPOLES], col, row; X pixel colors[MAXPOLES]; X X poles = cols * rows / 30000; X X /* Place and color poles randomly. */ X for ( i = 0; i < poles; i++ ) X { X xs[i] = random() % cols; X ys[i] = random() % rows; X colors[i] = random_bright_color( maxval ); X } X X /* Now interpolate points. */ X for ( row = 0; row < rows; row++ ) X for ( col = 0; col < cols; col++ ) X { X register long dist1, dist2, newdist, r, g, b; X pixel color1, color2; X X /* Find two closest poles. */ X dist1 = dist2 = 2000000000; X for ( i = 0; i < poles; i++ ) X { X newdist = ( col - xs[i] ) * ( col - xs[i] ) + X ( row - ys[i] ) * ( row - ys[i] ); X if ( newdist < dist1 ) X { X dist1 = newdist; X color1 = colors[i]; X } X else if ( newdist < dist2 ) X { X dist2 = newdist; X color2 = colors[i]; X } X } X X /* And assign interpolated color. */ X newdist = dist1 + dist2; X r = PPM_GETR(color1)*dist2/newdist + PPM_GETR(color2)*dist1/newdist; X g = PPM_GETG(color1)*dist2/newdist + PPM_GETG(color2)*dist1/newdist; X b = PPM_GETB(color1)*dist2/newdist + PPM_GETB(color2)*dist1/newdist; X PPM_ASSIGN( pixels[row][col], r, g, b ); X } X } X X/* Squig stuff. */ X X#define SQUIGS 5 X#define SQ_POINTS 7 X#define SQ_MAXCIRCLE_POINTS 5000 X Xint sq_radius, sq_circlecount; Xpixel sq_colors[SQ_MAXCIRCLE_POINTS]; Xint sq_xoffs[SQ_MAXCIRCLE_POINTS], sq_yoffs[SQ_MAXCIRCLE_POINTS]; X Xvoid Xsq_measurecircle_drawproc( pixels, cols, rows, maxval, col, row, clientdata ) Xpixel **pixels; Xint cols, rows, col, row; Xpixval maxval; Xchar *clientdata; X { X sq_xoffs[sq_circlecount] = col; X sq_yoffs[sq_circlecount] = row; X sq_circlecount++; X } X Xvoid Xsq_rainbowcircle_drawproc( pixels, cols, rows, maxval, col, row, clientdata ) Xpixel **pixels; Xint cols, rows, col, row; Xpixval maxval; Xchar *clientdata; X { X int i; X X for ( i = 0; i < sq_circlecount; i++ ) X ppmd_point_drawproc( X pixels, cols, rows, maxval, col + sq_xoffs[i], row + sq_yoffs[i], X &(sq_colors[i]) ); X } X Xsquig( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X pixel color; X int i, j, xc[SQ_POINTS], yc[SQ_POINTS], x0, y0, x1, y1, x2, y2, x3, y3; X X /* Clear image to black. */ X PPM_ASSIGN( color, 0, 0, 0 ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, X &color ); X X /* Draw the squigs. */ X (void) ppmd_setlinetype( PPMD_LINETYPE_NODIAGS ); X (void) ppmd_setlineclip( 0 ); X for ( i = SQUIGS; i > 0; i-- ) X { X /* Measure circle. */ X sq_radius = ( cols + rows ) / 2 / ( 25 + i * 2 ); X sq_circlecount = 0; X ppmd_circle( X pixels, cols, rows, maxval, 0, 0, sq_radius, X sq_measurecircle_drawproc, 0 ); X sq_assign_colors( sq_circlecount, maxval, sq_colors ); X X /* Choose wrap-around point. */ X switch ( random() % 4 ) X { X case 0: X x1 = random() % cols; X y1 = 0; X if ( x1 < cols / 2 ) X xc[0] = random() % ( x1 * 2 ); X else X xc[0] = cols - 1 - random() % ( ( cols - x1 ) * 2 ); X yc[0] = random() % rows; X x2 = x1; X y2 = rows - 1; X xc[SQ_POINTS - 1] = 2 * x2 - xc[0]; X yc[SQ_POINTS - 1] = y2 - yc[0]; X x0 = xc[SQ_POINTS - 1]; X y0 = yc[SQ_POINTS - 1] - rows; X x3 = xc[0]; X y3 = yc[0] + rows; X break; X X case 1: X x2 = random() % cols; X y2 = 0; X if ( x2 < cols / 2 ) X xc[SQ_POINTS - 1] = random() % ( x2 * 2 ); X else X xc[SQ_POINTS - 1] = cols - 1 - random() % ( ( cols - x2 ) * 2 ); X yc[SQ_POINTS - 1] = random() % rows; X x1 = x2; X y1 = rows - 1; X xc[0] = 2 * x1 - xc[SQ_POINTS - 1]; X yc[0] = y1 - yc[SQ_POINTS - 1]; X x0 = xc[SQ_POINTS - 1]; X y0 = yc[SQ_POINTS - 1] + rows; X x3 = xc[0]; X y3 = yc[0] - rows; X break; X X case 2: X x1 = 0; X y1 = random() % rows; X xc[0] = random() % cols; X if ( y1 < rows / 2 ) X yc[0] = random() % ( y1 * 2 ); X else X yc[0] = rows - 1 - random() % ( ( rows - y1 ) * 2 ); X x2 = cols - 1; X y2 = y1; X xc[SQ_POINTS - 1] = x2 - xc[0]; X yc[SQ_POINTS - 1] = 2 * y2 - yc[0]; X x0 = xc[SQ_POINTS - 1] - cols; X y0 = yc[SQ_POINTS - 1]; X x3 = xc[0] + cols; X y3 = yc[0]; X break; X X case 3: X x2 = 0; X y2 = random() % rows; X xc[SQ_POINTS - 1] = random() % cols; X if ( y2 < rows / 2 ) X yc[SQ_POINTS - 1] = random() % ( y2 * 2 ); X else X yc[SQ_POINTS - 1] = rows - 1 - random() % ( ( rows - y2 ) * 2 ); X x1 = cols - 1; X y1 = y2; X xc[0] = x1 - xc[SQ_POINTS - 1]; X yc[0] = 2 * y1 - yc[SQ_POINTS - 1]; X x0 = xc[SQ_POINTS - 1] + cols; X y0 = yc[SQ_POINTS - 1]; X x3 = xc[0] - cols; X y3 = yc[0]; X break; X } X X for ( j = 1; j < SQ_POINTS - 1; j++ ) X { X xc[j] = ( random() % ( cols - 2 * sq_radius ) ) + sq_radius; X yc[j] = ( random() % ( rows - 2 * sq_radius ) ) + sq_radius; X } X X ppmd_line( X pixels, cols, rows, maxval, x0, y0, x1, y1, X sq_rainbowcircle_drawproc, 0 ); X ppmd_polyspline( X pixels, cols, rows, maxval, x1, y1, SQ_POINTS, xc, yc, x2, y2, X sq_rainbowcircle_drawproc, 0 ); X ppmd_line( X pixels, cols, rows, maxval, x2, y2, x3, y3, X sq_rainbowcircle_drawproc, 0 ); X } X } X Xsq_assign_colors( circlecount, maxval, colors ) Xint circlecount; Xpixval maxval; Xpixel *colors; X { X pixel rc1, rc2, rc3; X float cco3; X int i; X X rc1 = random_bright_color( maxval ); X rc2 = random_bright_color( maxval ); X rc3 = random_bright_color( maxval ); X cco3 = ( circlecount - 1 ) / 3.0; X X for ( i = 0; i < circlecount ; i++ ) X { X if ( i < cco3 ) X PPM_ASSIGN( X colors[i], X (float) PPM_GETR(rc1) + X ( (float) PPM_GETR(rc2) - (float) PPM_GETR(rc1) ) * X (float) i / cco3, X (float) PPM_GETG(rc1) + X ( (float) PPM_GETG(rc2) - (float) PPM_GETG(rc1) ) * X (float) i / cco3, X (float) PPM_GETB(rc1) + X ( (float) PPM_GETB(rc2) - (float) PPM_GETB(rc1) ) * X (float) i / cco3 ); X else if ( i < 2.0 * cco3 ) X PPM_ASSIGN( X colors[i], X (float) PPM_GETR(rc2) + X ( (float) PPM_GETR(rc3) - (float) PPM_GETR(rc2) ) * X ( (float) i / cco3 - 1.0 ), X (float) PPM_GETG(rc2) + X ( (float) PPM_GETG(rc3) - (float) PPM_GETG(rc2) ) * X ( (float) i / cco3 - 1.0 ), X (float) PPM_GETB(rc2) + X ( (float) PPM_GETB(rc3) - (float) PPM_GETB(rc2) ) * X ( (float) i / cco3 - 1.0 ) ); X else X PPM_ASSIGN( X colors[i], X (float) PPM_GETR(rc3) + X ( (float) PPM_GETR(rc1) - (float) PPM_GETR(rc3) ) * X ( (float) i / cco3 - 2.0 ), X (float) PPM_GETG(rc3) + X ( (float) PPM_GETG(rc1) - (float) PPM_GETG(rc3) ) * X ( (float) i / cco3 - 2.0 ), X (float) PPM_GETB(rc3) + X ( (float) PPM_GETB(rc1) - (float) PPM_GETB(rc3) ) * X ( (float) i / cco3 - 2.0 ) ); X } X } X X/* Camouflage stuff. */ X Xpixel Xrandom_camo_color( maxval ) Xpixval maxval; X { X int v1, v2, v3; X pixel p; X X v1 = ( (int) maxval + 1 ) / 8; X v2 = ( (int) maxval + 1 ) / 4; X v3 = ( (int) maxval + 1 ) / 2; X X switch ( random() % 10 ) X { X case 0: case 1: case 2: /* light brown */ X PPM_ASSIGN( X p, random() % v3 + v3, random() % v3 + v2, random() % v3 + v2 ); X break; X X case 3: case 4: case 5: /* dark green */ X PPM_ASSIGN( p, random() % v2, random() % v2 + 3 * v1, random() % v2 ); X break; X X case 6: case 7: /* brown */ X PPM_ASSIGN( p, random() % v2 + v2, random() % v2, random() % v2 ); X break; X X case 8: case 9: /* dark brown */ X PPM_ASSIGN( p, random() % v1 + v1, random() % v1, random() % v1 ); X break; X } X X return p; X } X Xpixel Xrandom_anticamo_color( maxval ) Xpixval maxval; X { X int v1, v2, v3; X pixel p; X X v1 = ( (int) maxval + 1 ) / 4; X v2 = ( (int) maxval + 1 ) / 2; X v3 = 3 * v1; X X switch ( random() % 15 ) X { X case 0: case 1: X PPM_ASSIGN( p, random() % v1 + v3, random() % v2, random() % v2 ); X break; X X case 2: case 3: X PPM_ASSIGN( p, random() % v2, random() % v1 + v3, random() % v2 ); X break; X X case 4: case 5: X PPM_ASSIGN( p, random() % v2, random() % v2, random() % v1 + v3 ); X break; X X case 6: case 7: case 8: X PPM_ASSIGN( p, random() % v2, random() % v1 + v3, random() % v1 + v3 ); X break; X X case 9: case 10: case 11: X PPM_ASSIGN( p, random() % v1 + v3, random() % v2, random() % v1 + v3 ); X break; X X case 12: case 13: case 14: X PPM_ASSIGN( p, random() % v1 + v3, random() % v1 + v3, random() % v2 ); X break; X X } X X return p; X } X Xfloat Xrnduni( ) X { X return random() % 1000000L / 1000000.0; X } X X#define BLOBRAD 50 X X#define MIN_POINTS 7 X#define MAX_POINTS 13 X X#define MIN_ELLIPSE_FACTOR 0.5 X#define MAX_ELLIPSE_FACTOR 2.0 X X#define MIN_POINT_FACTOR 0.5 X#define MAX_POINT_FACTOR 2.0 X Xcamo( pixels, cols, rows, maxval, antiflag ) Xpixel **pixels; Xint cols, rows, antiflag; Xpixval maxval; X { X pixel color; X int n, i, cx, cy; X char *fh; X X /* Clear background. */ X if ( antiflag ) X color = random_anticamo_color( maxval ); X else X color = random_camo_color( maxval ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, X &color ); X X n = ( rows * cols ) / ( BLOBRAD * BLOBRAD ) * 5; X for ( i = 0; i < n; i++ ) X { X int points, p, xs[MAX_POINTS], ys[MAX_POINTS], x0, y0; X float a, b, c, theta, tang, tx, ty; X X cx = random() % cols; X cy = random() % rows; X X points = random() % ( MAX_POINTS - MIN_POINTS + 1 ) + MIN_POINTS; X a = rnduni() * ( MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR ) + X MIN_ELLIPSE_FACTOR; X b = rnduni() * ( MAX_ELLIPSE_FACTOR - MIN_ELLIPSE_FACTOR ) + X MIN_ELLIPSE_FACTOR; X theta = rnduni() * 2.0 * M_PI; X for ( p = 0; p < points; p++ ) X { X tx = a * sin( p * 2.0 * M_PI / points ); X ty = b * cos( p * 2.0 * M_PI / points ); X tang = atan2( ty, tx ) + theta; X c = rnduni() * ( MAX_POINT_FACTOR - MIN_POINT_FACTOR ) + X MIN_POINT_FACTOR; X xs[p] = cx + BLOBRAD * c * sin( tang ); X ys[p] = cy + BLOBRAD * c * cos( tang ); X } X x0 = ( xs[0] + xs[points - 1] ) / 2; X y0 = ( ys[0] + ys[points - 1] ) / 2; X X fh = ppmd_fill_init(); X X ppmd_polyspline( X pixels, cols, rows, maxval, x0, y0, points, xs, ys, x0, y0, X ppmd_fill_drawproc, fh ); X X if ( antiflag ) X color = random_anticamo_color( maxval ); X else X color = random_camo_color( maxval ); X ppmd_fill( pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color ); X } X } X X/* Test pattern. Just a place to put ppmdraw exercises. */ X Xtest( pixels, cols, rows, maxval ) Xpixel **pixels; Xint cols, rows; Xpixval maxval; X { X pixel color; X char *fh; X X /* Clear image to black. */ X PPM_ASSIGN( color, 0, 0, 0 ); X ppmd_filledrectangle( X pixels, cols, rows, maxval, 0, 0, cols, rows, PPMD_NULLDRAWPROC, X &color ); X X fh = ppmd_fill_init(); X X ppmd_line( pixels, cols, rows, maxval, cols/8, rows/8, cols-cols/8, rows/4, ppmd_fill_drawproc, fh ); X ppmd_line( pixels, cols, rows, maxval, cols-cols/8, rows/4, cols/2, rows/2, ppmd_fill_drawproc, fh ); X 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 ); X 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 ); X ppmd_line( pixels, cols, rows, maxval, cols/4, rows/2, cols/8, rows/2, ppmd_fill_drawproc, fh ); X ppmd_line( pixels, cols, rows, maxval, cols/8, rows/2, cols/8, rows/8, ppmd_fill_drawproc, fh ); X X PPM_ASSIGN( color, maxval, maxval, maxval ); X ppmd_fill( pixels, cols, rows, maxval, fh, PPMD_NULLDRAWPROC, &color ); X } SHAR_EOF if test 27285 -ne "`wc -c < 'ppm/ppmpat.c'`" then echo shar: error transmitting "'ppm/ppmpat.c'" '(should have been 27285 characters)' fi fi # end of overwriting check # End of shell archive exit 0