cheeks@arsenic..eds.com (Mark Costlow) (05/26/91)
This is a program for generating/displaying plasma cloud images for X11. Here's part of the README: This is plasma. It implements "plasma clouds" with X11. It's not very sophisticated ... I just saw jjensen@dsg4.dse.beckman.com (John Jensen)'s post in alt.fractals and coded up his ideas (and used some of his code) with my Xlib skeleton which I use for prototyping graphics ideas. It does colormap cycling, and it lets you mess with a few of the parameters. Enjoy ... Mark cheeks@edsr.eds.com or ...uunet!edsr!cheeks #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Mark Costlow <cheeks@argon> on Sat May 25 20:30:25 1991 # # This archive contains: # README Makefile plasma.c # # Existing files will not be overwritten. # Error checking via wc(1) will be performed. LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH if test -f README then echo Ok to overwrite existing file README\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f README if test -f README then echo Error: could not remove README, aborting exit 1 fi fi echo x - README cat >README <<'@EOF' This is plasma. It implements "plasma clouds" with X11. It's not very sophisticated ... I just saw jjensen@dsg4.dse.beckman.com (John Jensen)'s post in alt.fractals and coded up his ideas (and used some of his code) with my Xlib skeleton which I use for prototyping graphics ideas. It does colormap cycling, and it lets you mess with a few of the parameters. It definitely works with sparcs under SunOS 4.1.x and 8 bit displays. My skeleton runs on HPs under hpux as well, even with those gnarly 6-bit displays, but I haven't tested it with this program. I don't really have time to "maintain" this thing ... I'm just throwing it out since it's kinda cute. I'll fix bugs as time permits though, and I would like to hear about changes or improvements (like getting it to use the default color map and running on the root window, etc). It is hereby placed in the public domain ... give it away, sell it, whatever. I'd appreciate it if my name was left on it though. Mark Costlow cheeks@edsr.eds.com or ...uunet!edsr!cheeks @EOF set `wc -lwc <README` if test $1$2$3 != 191781038 then echo ERROR: wc results of README are $* should be 19 178 1038 fi chmod 664 README if test -f Makefile then echo Ok to overwrite existing file Makefile\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f Makefile if test -f Makefile then echo Error: could not remove Makefile, aborting exit 1 fi fi echo x - Makefile cat >Makefile <<'@EOF' CC = gcc CFLAGS = -g .c.o: $(CC) $(CFLAGS) -c $< PROGS = plasma all: $(PROGS) plasma: plasma.o $(CC) $(CFLAGS) -o plasma plasma.o -lX11 -lm clean: rm -f core *.o $(PROGS) @EOF set `wc -lwc <Makefile` if test $1$2$3 != 1531180 then echo ERROR: wc results of Makefile are $* should be 15 31 180 fi chmod 664 Makefile if test -f plasma.c then echo Ok to overwrite existing file plasma.c\? read answer case "$answer" in [yY]*) echo Proceeding;; *) echo Aborting; exit 1;; esac rm -f plasma.c if test -f plasma.c then echo Error: could not remove plasma.c, aborting exit 1 fi fi echo x - plasma.c cat >plasma.c <<'@EOF' /* * plasma.c -- generate/display plasma clouds with X11. It was written in * about an hour ... and the code shows it :-). * * Mark Costlow * cheeks@edsr.eds.com * May 25, 1991 */ #include <stdio.h> #include <math.h> #include <ctype.h> /* X-windows includes */ #include <X11/Xos.h> #include <X11/Xatom.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/cursorfont.h> typedef unsigned char byte; double drand48(); Display *display; char win_name[64]; Visual *visual = NULL; Status status; unsigned long wp, bp; /* pixel values for black & white */ int screen, nplanes, ncolors; XEvent event; XExposeEvent *expose; XSetWindowAttributes attrib; GC gc; XGCValues gc_val; XSizeHints sizehints; Window imagewin; /* window ID for image */ XImage *image = NULL; Colormap *cmaps; double Futz = 2.0; /* Global scale of random perturbations. */ int usedist = 1; /* Use distance to scale perturbations. */ int sleep_delay = 50000; /* speed of colormap cyling. */ int global_x, global_y; byte *buf; #define BUF(a,b) buf[(global_y * b) + a] #define NUMCOLORS 255 void MakeColormaps(int nplanes) { XColor colors[256]; int i, j, mask, tempcolor; Colormap cmap; double step, f; fprintf(stderr, "Building color maps . . . "); fflush(stderr); ncolors = 1 << nplanes; cmaps = (Colormap *) malloc(ncolors * sizeof(Colormap)); step = (double) ( (M_PI_4 * (double)nplanes) / (double) ncolors); f = M_PI; /* + M_PI_2; */ #define MAXI 65535 for (i = 0; i < ncolors; i++) { double wank = MAXI / 2.0; double sin(double); #define PLAIN colors[i].pixel = i; colors[i].flags = DoRed | DoGreen | DoBlue; #ifdef PLAIN colors[i].red = (int)((wank * sin(f)) + wank); colors[i].green = (int)((wank * sin(f + M_PI)) + wank); colors[i].blue = (int)((wank * sin(f + M_PI + M_PI_2)) + wank); #else colors[i].red = (int)((wank * sin(f)) + wank); colors[i].green = (int)((wank * sin(f + M_PI_4)) + wank); colors[i].blue = (int)((wank * sin(f + M_PI_2)) + wank); #endif f += step; } for (j = 0; j < ncolors; j++) { tempcolor = colors[0].pixel; for (i = 0; i < ncolors - 1; i++) colors[i].pixel = colors[i+1].pixel; colors[ncolors-1].pixel = tempcolor; cmaps[j] = XCreateColormap(display, RootWindow(display, screen), visual, AllocAll); XStoreColors(display, cmaps[j], colors, ncolors); } fprintf(stderr, "Done\n"); fflush(stderr); } void CycleColormap() { static int current_map = 0; XSetWindowColormap(display, imagewin, cmaps[current_map++]); current_map = (current_map % ncolors); XSync(display, False); } void InitX(char *disp, int x, int y) { int i, j; strcpy(win_name, "Plasma"); /* * Open the connection to the X11 server and set defaults */ if ((display = XOpenDisplay(disp)) == NULL) { fprintf(stderr,"Could not open display.\n"); exit(1); } screen = XDefaultScreen(display); visual = XDefaultVisual(display, screen); nplanes = XDisplayPlanes(display, screen); bp = BlackPixel(display, screen); wp = WhitePixel(display, screen); /* * Set window manager hints */ sizehints.flags = PPosition | PSize | PMinSize | PMaxSize; sizehints.width = sizehints.min_width = x; sizehints.max_width = x; sizehints.height = sizehints.min_height = y; sizehints.max_height = x; sizehints.x = 0; sizehints.y = 0; MakeColormaps(nplanes); attrib.background_pixel = wp; attrib.border_pixel = bp; attrib.event_mask = (ExposureMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | ColormapChangeMask | Button1MotionMask | EnterWindowMask); attrib.cursor = XCreateFontCursor(display, XC_top_left_arrow); /* * Create the window. */ imagewin = XCreateWindow(display, RootWindow(display, screen), 0, 0, x, y, 5, XDefaultDepth(display, screen), InputOutput, visual, (CWBackPixel|CWEventMask|CWCursor|CWBorderPixel), &attrib); /* * Install properties for the window. */ XSetStandardProperties(display, imagewin, win_name, win_name, NULL, NULL, NULL, &sizehints); XSetIconName(display, imagewin, "Plasma"); /* * Install the colormap */ XSetWindowColormap(display, imagewin, cmaps[0]); /* #define DEBUG */ #ifdef DEBUG /* * See what's in the colormap */ for (j = 0; j < (1<<nplanes); j++) { for (i=0; i < (1 << nplanes); i++) { XColor qcolor; qcolor.pixel = (u_long)i; XQueryColor(display, cmaps[j], &qcolor); fprintf(stderr,"color[%2d]: pix %3u r= %5u g= %5u b= %5u\n",i, qcolor.pixel, qcolor.red, qcolor.green, qcolor.blue); } } fprintf(stderr, "\n\n"); #endif /* * Now finally map the window ... */ XMapWindow(display, imagewin); /* * Create a Graphics Context. */ gc_val.foreground = bp; gc_val.background = wp; gc = XCreateGC(display, imagewin, GCForeground | GCBackground , &gc_val); /* * select which input events to honor */ XSelectInput(display, imagewin, (ExposureMask | KeyPressMask)); /* * Wait for first expose event */ XNextEvent(display, &event); while (event.type != Expose) { XNextEvent(display, &event); } } show_pic(byte *buf, int x, int y) { char ch, tmp[80]; static int ngen = 0; image = XCreateImage(display, visual, nplanes, ZPixmap, 0, (char *)buf, x, y, 8, 0); XPutImage(display, imagewin, gc, image, 0, 0, 0, 0, x, y); XSync(display, False); } /* * Enter infinite loop to sevice events. */ void manage_window() { int Finished; XKeyEvent *keypress; KeySym keysym; char keybuf[64]; XComposeStatus cstat; Finished = 0; expose = (XExposeEvent *)&event; keypress = (XKeyEvent *)&event; while (!Finished) { if (XPending(display)) { XNextEvent(display, &event); switch ((int)event.type) { case Expose: if (expose->x % 4 != 0) { expose->x -= (expose->x % 4); expose->width += (expose->x % 4); } if (expose->width % 4 != 0) expose->width += 4 - (expose->width % 4); XPutImage(display, imagewin, gc, image, expose->x, expose->y, expose->x, expose->y, expose->width, expose->height); break; case ButtonPress: Finished = 1; break; case KeyPress: XLookupString(keypress, keybuf, sizeof(keybuf), &keysym, &cstat); if(*keybuf == 'q' || *keybuf == 'Q') Finished = 1; break; default: break; } } usleep(sleep_delay); CycleColormap(); } } adjust(int xa, int ya, int x, int y, int xb, int yb) { int d; double v; if (usedist) d = abs(xa - xb) + abs(ya - yb); else d = 1.0; v = (BUF(xa, ya) + BUF(xb, yb)) / 2 + (drand48() - 0.5) * d * Futz; if (v < 1.0) v = 1.0; else if (v > (double)NUMCOLORS) v = (double)NUMCOLORS; BUF(x, y) = (int)v; } subdivide(int x1, int y1, int x2, int y2) { int x, y, v; if ((x2 - x1 > 1) || (y2 - y1 > 1)) { x = (x1 + x2) / 2; y = (y1 + y2) / 2; if (!BUF(x,y1)) adjust(x1, y1, x, y1, x2, y1); if (!BUF(x2,y)) adjust(x2, y1, x2, y, x2, y2); if (!BUF(x,y2)) adjust(x1, y2, x, y2, x2, y2); if (!BUF(x1,y)) adjust(x1, y1, x1, y, x1, y2); if (!BUF(x, y)) { v = (BUF(x1, y1) + BUF(x2, y1) + BUF(x2, y2) + BUF(x1, y2)) / 4; if (v < 1) v = 1; else if (v > NUMCOLORS) v = NUMCOLORS; BUF(x, y) = v; } subdivide(x1, y1, x, y); subdivide(x, y1, x2, y); subdivide(x, y, x2, y2); subdivide(x1, y, x, y2); /* show_pic(buf, global_x, global_y); */ } } void Usage(char *prog, char *opt) { fprintf(stderr, "%s: bad option \"%s\"\n\n", prog, opt); fprintf(stderr, "Usage: %s [options]\n\nWhere options include:\n", prog); fprintf(stderr," -f <num>\t\t Set global futz factor (default = 2.0)\n"); fprintf(stderr," -dist\t\t Don't make perturbations dependent on dist.\n"); fprintf(stderr," -delay <num>\t Delay in colormap rotation. (default = 1.0).\n"); fprintf(stderr," -display <host:#>\t Specify alternate X server\n"); fprintf(stderr," -s <size>\t\t Use a <size>-square area\n\n"); exit(1); } main (int argc, char **argv) { char *display = NULL; int x, y, X, Y, i, j; int size = 0, testcolor = 0, matrix_size = 4; int xsize = 100, ysize = 100; /* Initialize the random number generator */ srand48(getpid()); i = 0; for(i = 1; i < argc; i++) { if (! strncmp("-s", argv[i], 2) && i+1 < argc) size = atoi(argv[++i]); else if (! strncmp("-x", argv[i], 2) && i+1 < argc) xsize = atoi(argv[++i]); else if (! strncmp("-y", argv[i], 2) && i+1 < argc) ysize = atoi(argv[++i]); else if (! strncmp("-f", argv[i], 2) && i+1 < argc) Futz = atof(argv[++i]); else if (! strncmp("-display", argv[i], 8) && i+1 < argc) display = argv[++i]; else if (! strncmp("-delay", argv[i], 6) && i+1 < argc) sleep_delay = (int) ((double)sleep_delay * atof(argv[++i])); else if (! strncmp("-dist", argv[i], 5)) usedist = 0; else Usage(argv[0], argv[i]); } if (size) global_x = global_y = x = y = size; else { global_x = x = xsize; global_y = y = ysize; } buf = (byte *)malloc(x * y); if (!buf) { fprintf(stderr, "%s: malloc failure.\n", argv[0]); exit(1); } memset(buf, 0, x * y); /* * Prime the 4 corners with random colors. */ BUF(0,0) = (int)( (drand48() * NUMCOLORS) + 1.0 ); BUF(x-1,0) = (int)( (drand48() * NUMCOLORS) + 1.0 ); BUF(x-1,y-1) = (int)( (drand48() * NUMCOLORS) + 1.0 ); BUF(0,y-1) = (int)( (drand48() * NUMCOLORS) + 1.0 ); fprintf(stderr, "Subdividing ..."); fflush(stderr); subdivide(0, 0, x-1, y-1); fprintf(stderr, " done\n"); fflush(stderr); InitX(display, x, y); show_pic(buf, x, y); manage_window(); exit(0); } @EOF set `wc -lwc <plasma.c` if test $1$2$3 != 418135110205 then echo ERROR: wc results of plasma.c are $* should be 418 1351 10205 fi chmod 664 plasma.c exit 0 -- cheeks@edsr.eds.com or ...uunet!edsr!cheeks