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 ); }