[comp.sources.sun] v01i019: Color Splines: Part 01/01

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (05/28/89)

Submitted-by:     Jef Poskanzer <jef@helios.ee.lbl.gov>
Posting-number: Volume 1, Issue 19
Archive-name: colorsplines

   A cute hack indeed!  Note that this posting is not in 'shar'
format, since its only the one file.  Save it as spf3.c.  Runs on sun3's
and sun4's - but only on color machines.  

						Charles

/*
** spf3.c - spline fun #3
**
** Compile: cc -O spf3.c -lpixrect -o spf3
**
** Run:
**   spf3		spline fun
**   spf3 -b		spline fun with backwards colormap cycling
**   spf3 -f		spline fun with forwards colormap cycling
**
** Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation.  This software is provided "as is" without express or
** implied warranty.
**
** Comments to:
**   jef@helios.ee.lbl.gov
**   {ucbvax, lll-crg, sun!pacbell, apple, hplabs}!well!pokey
**
*/

#define POINTS 5
#define MAXDELTA 3
#define MAXCOLORDELTA 3

#include <stdio.h>
#include <sys/file.h>
#include <signal.h>
#include <sys/types.h>
#include <pixrect/pixrect_hs.h>

static unsigned char oldred[256], oldgreen[256], oldblue[256];
static int oldplanes;
static Pixrect *disp_pr;

main( argc, argv )
int argc;
char *argv[];
    {
    int argn, forward, backward;
    int width, height, i, t, color;
    int x[POINTS], y[POINTS], dx[POINTS], dy[POINTS];
    int px, py, nx, ny, zx, zy;
    unsigned char red[256], green[256], blue[256];
    int dred, dgreen, dblue;
    unsigned char nred, ngreen, nblue, tred, tgreen, tblue;
#define MAXGROUPS 10
    char groups[MAXGROUPS];
    Pixrect *my_pr_open();
    int terminate();
    char *usage = "usage:  %s [-f|-b]\n";

    argn = 1;
    forward = 0;
    backward = 0;

    if ( argn < argc )
	{
	if ( strcmp( argv[argn], "-f" ) == 0 )
	    forward = 1;
	else if ( strcmp( argv[argn], "-b" ) == 0 )
	    backward = 1;
	else
	    {
	    fprintf( stderr, usage, argv[0] );
	    exit( 1 );
	    }
	argn++;
	}

    if ( argn != argc )
	{
	fprintf( stderr, usage, argv[0] );
	exit( 1 );
	}

    if ( (disp_pr = my_pr_open( "/dev/cgfive0" )) == (Pixrect *) 0 )
      if ( (disp_pr = my_pr_open( "/dev/cgthree0" )) == (Pixrect *) 0 )
	if ( (disp_pr = my_pr_open( "/dev/gpone0a" )) == (Pixrect *) 0 )
	  if ( (disp_pr = my_pr_open( "/dev/cgtwo0" )) == (Pixrect *) 0 )
	    if ( (disp_pr = my_pr_open( "/dev/cgfour0" )) == (Pixrect *) 0 )
	      if ( (disp_pr = my_pr_open( "/dev/cgone0" )) == (Pixrect *) 0 )
	        if ( (disp_pr = my_pr_open( "/dev/fb" )) == (Pixrect *) 0 )
	        {
	        fprintf( stderr, "%s: error opening display\n", argv[0] );
	        exit( 1 );
	        }

    /* Save old state. */
    pr_getcolormap( disp_pr, 0, 256, oldred, oldblue, oldgreen );
    oldplanes = pr_get_plane_group( disp_pr );
    signal( SIGHUP, terminate );
    signal( SIGINT, terminate );
    signal( SIGTERM, terminate );

    width = disp_pr->pr_size.x;
    height = disp_pr->pr_size.y;

    srandom( (int) time( 0 ) );

    (void) pr_available_plane_groups( disp_pr, MAXGROUPS, groups );
    if ( ! groups[PIXPG_8BIT_COLOR] )
	{
	fprintf( stderr, "%s: display must implement 8-bit color\n", argv[0] );
	exit( 1 );
	}
    pr_set_plane_group( disp_pr, PIXPG_8BIT_COLOR );
    nred = ngreen = nblue = 0;
    red[0] = green[0] = blue[0] = 255;
    for ( color = 1; color < 256; color++ )
	red[color] = green[color] = blue[color] = 0;
    pr_putcolormap( disp_pr, 0, 256, red, green, blue );
    pr_rop( disp_pr, 0, 0, width, height, PIX_SRC | PIX_COLOR(1), 0, 0, 0 );
    signit( disp_pr );

    dred = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
    if ( dred <= 0 ) dred--;
    dgreen = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
    if ( dgreen <= 0 ) dgreen--;
    dblue = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
    if ( dblue <= 0 ) dblue--;
    for ( i = 0; i < POINTS; i++ )
	{
	x[i] = random() % width;
	y[i] = random() % height;
	dx[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA;
	if ( dx[i] <= 0 ) dx[i]--;
	dy[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA;
	if ( dy[i] <= 0 ) dy[i]--;
	}

    /* Main loop. */
    color = 1;
    for ( ; ; )
	{
	/* Choose new color. */
	if ( ++color == 256 ) color = 2;
	for ( ; ; )
	    {
	    t = (int) nred + dred;
	    if ( t >= 0 && t < 256 ) break;
	    dred = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
	    if ( dred <= 0 ) dred--;
	    }
	red[color] = nred = t;
	for ( ; ; )
	    {
	    t = (int) ngreen + dgreen;
	    if ( t >= 0 && t < 256 ) break;
	    dgreen = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
	    if ( dgreen <= 0 ) dgreen--;
	    }
	green[color] = ngreen = t;
	for ( ; ; )
	    {
	    t = (int) nblue + dblue;
	    if ( t >= 0 && t < 256 ) break;
	    dblue = random() % ( MAXCOLORDELTA * 2 ) - MAXCOLORDELTA;
	    if ( dblue <= 0 ) dblue--;
	    }
	blue[color] = nblue = t;
	pr_putcolormap( disp_pr, 0, 256, red, green, blue );

	/* Move the points. */
	for ( i = 0; i < POINTS; i++ )
	    {
	    for ( ; ; )
		{
		t = x[i] + dx[i];
		if ( t >= 0 && t < width ) break;
		dx[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA;
		if ( dx[i] <= 0 ) dx[i]--;
		}
	    x[i] = t;
	    for ( ; ; )
		{
		t = y[i] + dy[i];
		if ( t >= 0 && t < height ) break;
		dy[i] = random() % ( MAXDELTA * 2 ) - MAXDELTA;
		if ( dy[i] <= 0 ) dy[i]--;
		}
	    y[i] = t;
	    }

	/* Draw the figure. */
	px = zx = ( x[0] + x[POINTS-1] ) / 2;
	py = zy = ( y[0] + y[POINTS-1] ) / 2;
	for ( i = 0; i < POINTS-1; i++ )
	    {
	    nx = ( x[i+1] + x[i] ) / 2;
	    ny = ( y[i+1] + y[i] ) / 2;
	    pr_spline3(
		disp_pr, px, py, x[i], y[i], nx, ny,
		PIX_SRC | PIX_COLOR(color), 0 );
	    px = nx;
	    py = ny;
	    }
	pr_spline3(
	    disp_pr, px, py, x[POINTS-1], y[POINTS-1], zx, zy,
	    PIX_SRC | PIX_COLOR(color), 0 );

	/* Cycle colormap. */
	if ( forward )
	    {
	    if ( color % 2 == 0 )
		{
		/* Cycle colors forward. */
		tred = red[255];
		tgreen = green[255];
		tblue = blue[255];
		for ( i = 254; i >= 2; i-- )
		    {
		    red[i+1] = red[i];
		    green[i+1] = green[i];
		    blue[i+1] = blue[i];
		    }
		red[2] = tred;
		green[2] = tgreen;
		blue[2] = tblue;
		}
	    }
	else if ( backward )
	    {
	    /* Cycle colors backward. */
	    tred = red[2];
	    tgreen = green[2];
	    tblue = blue[2];
	    for ( i = 3; i <= 255; i++ )
		{
		red[i-1] = red[i];
		green[i-1] = green[i];
		blue[i-1] = blue[i];
		}
	    red[255] = tred;
	    green[255] = tgreen;
	    blue[255] = tblue;
	    red[color] = nred;
	    green[color] = ngreen;
	    blue[color] = nblue;
	    }
	}
    }

Pixrect *
my_pr_open( fb )
char *fb;
    {
    int fd;

    /* Test with open first, to avoid stupid error messages from pr_open(). */
    if ( (fd = open(fb, O_RDWR)) == -1 )
	return (Pixrect *) 0;
    close( fd );
    return pr_open( fb );
    }

static short posk_image[] = {
    0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
    0xffff,0xffff,0xffff,0xffff,0xffe7,0xcfff,0xffe7,0xcfff,
    0xffe7,0x9fff,0xffcf,0xbfff,0xffcf,0x3fff,0xffdf,0x507f,
    0xff8e,0x7e3f,0xff6e,0x7e7f,0xffcf,0x7e3f,0xffcf,0x7c7f,
    0xffcf,0x067f,0xffcf,0x0e7f,0xffce,0x7e7f,0xffcf,0x7c7f,
    0xffce,0x2a7f,0xffcf,0x14ff,0xffcf,0xfcff,0xffcf,0xffff,
    0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xfffc,0x7fff,
    0xfffe,0x3fff,0xfffe,0x3fff,0xfffe,0x3fff,0xfffe,0x3fff,
    0xffff,0x3fff,0xfffe,0x107f,0xffa0,0x007f,0xfc1e,0x3fff,
    0xffff,0x3fff,0xfffe,0x1fff,0xffff,0x3fff,0xfffe,0x3fff,
    0xfffe,0x3fff,0xffff,0x3fff,0xfffe,0x2bff,0xffe8,0x01ff,
    0xff05,0xd8ff,0xff7f,0xffff,0xffff,0xffff,0xff83,0xfcff,
    0xfe67,0xe0ff,0xfe47,0x9dff,0xfe13,0xf9ff,0xfe7b,0xb3ff,
    0xfe43,0x87ff,0xfe27,0xc7ff,0xfe65,0xc3ff,0xfc00,0x707f,
    0xfe3e,0x7c3f,0xffff,0x3fff,0xffff,0x2fff,0xfff8,0x1fff,
    0xfffe,0x2fff,0xffe0,0x01ff,0xff82,0xa8ff,0xffff,0xffff,
    0xffff,0xffff,0xffff,0xefff,0xffff,0xe7ff,0xffc7,0xe7ff,
    0xfff3,0xe7ff,0xffff,0xe7ff,0xffdf,0x667f,0xff1f,0x263f,
    0xffdf,0x27ff,0xffff,0x69ff,0xfffd,0xc1ff,0xfffb,0xe1ff,
    0xfffb,0xf1ff,0xfff7,0xf3ff,0xfff7,0xe7ff,0xffe7,0xc7ff,
    0xffef,0xcfff,0xffcf,0x9fff,0xff8f,0x3fff,0xff9e,0x7fff,
    0xffdc,0xffff,0xfffb,0xffff,0xffff,0xffff,0xffff,0xffff,
    0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff };
mpr_static( posk, 32, 92, 1, posk_image );

signit( pr )
Pixrect *pr;
    {
#ifdef sun386
    pr_flip( &posk );
#endif sun386

    pr_rop(
	pr, pr->pr_size.x - posk.pr_size.x, pr->pr_size.y - posk.pr_size.y,
	posk.pr_size.x, posk.pr_size.y,
	PIX_SRC | PIX_COLOR(1), &posk, 0, 0 );
    }

int
terminate( sig, code, scp )
int sig, code;
struct sigcontext *scp;
    {
    pr_putcolormap( disp_pr, 0, 256, oldred, oldgreen, oldblue );
    pr_set_plane_group( disp_pr, oldplanes );
    pr_rop(
	disp_pr, 0, 0, disp_pr->pr_size.x, disp_pr->pr_size.y,
	PIX_CLR, 0, 0, 0 );
    exit( 0 );
    }


#define abs(x) ((x) < 0 ? -(x) : (x))
#define SPLINE_THRESH 3

pr_spline3( pr, x0, y0, x1, y1, x2, y2, op, value )
Pixrect *pr;
int x0, y0, x1, y1, x2, y2, op, value;
    {
    register int xa, ya, xb, yb, xc, yc, xp, yp;

    xa = ( x0 + x1 ) / 2;
    ya = ( y0 + y1 ) / 2;
    xc = ( x1 + x2 ) / 2;
    yc = ( y1 + y2 ) / 2;
    xb = ( xa + xc ) / 2;
    yb = ( ya + yc ) / 2;

    xp = ( x0 + xb ) / 2;
    yp = ( y0 + yb ) / 2;
    if ( abs( xa - xp ) + abs( ya - yp ) > SPLINE_THRESH )
	pr_spline3( pr, x0, y0, xa, ya, xb, yb, op, value );
    else
	pr_vector( pr, x0, y0, xb, yb, op, value );

    xp = ( x2 + xb ) / 2;
    yp = ( y2 + yb ) / 2;
    if ( abs( xc - xp ) + abs( yc - yp ) > SPLINE_THRESH )
	pr_spline3( pr, xb, yb, xc, yc, x2, y2, op, value );
    else
	pr_vector( pr, xb, yb, x2, y2, op, value );
    }