home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
x
/
volume18
/
xmandel
/
part03
< prev
next >
Wrap
Internet Message Format
|
1992-07-13
|
50KB
Path: uunet!elroy.jpl.nasa.gov!swrinde!mips!msi!dcmartin
From: tony@ajfcal.cuc.ab.ca (Tony Field)
Newsgroups: comp.sources.x
Subject: v18i017: Xmandelbrot, Part03/03
Message-ID: <1992Jul13.155107.6740@msi.com>
Date: 13 Jul 92 15:51:07 GMT
References: <csx-18i015-xmandel@uunet.UU.NET>
Sender: dcmartin@msi.com (David C. Martin - Moderator)
Organization: Molecular Simulations, Inc.
Lines: 1759
Approved: dcmartin@msi.com
Originator: dcmartin@fascet
Submitted-by: tony@ajfcal.cuc.ab.ca (Tony Field)
Posting-number: Volume 18, Issue 17
Archive-name: xmandel/part03
#!/bin/sh
# this is part.03 (part 3 of a multipart archive)
# do not concatenate these parts, unpack them in order with /bin/sh
# file mandel.c continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 3; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping mandel.c'
else
echo 'x - continuing file mandel.c'
sed 's/^X//' << 'SHAR_EOF' >> 'mandel.c' &&
X
void start_mandel()
{
X if (manparm.window == 0)
X return;
X if (manparm.zoom)
X { /* reset to beginning by popping zps off stack if not already there */
X while (zoomtmp = manparm.zoom->zp)
X { free(manparm.zoom);
X manparm.zoom = zoomtmp;
X }
X }
X else
X { manparm.zoom = (struct zoomd *) malloc(sizeof (struct zoomd));
X manparm.zoom->zp = NULL; /* NULL means last in stack - don't pop */
X }
X manparm.zoom->lx = START_LX; manparm.zoom->ux = START_UX;
X manparm.zoom->ly = START_LY; manparm.zoom->uy = START_UY;
X
X mandel ();
}
X
/************************************************************************
* redo_mandel() button: recalc recalc current mandelbrot *
************************************************************************/
X
void redo_mandel ()
{ if (manparm.window == 0)
X return;
X mandel ();
}
X
X
/************************************************************************
* mandel() do the mandelbrot calculations and send to video*
************************************************************************/
X
static void mandel ()
{
X double wx, wy, oldwx;
X double x, y;
X double incrx, incry;
X int ix, iy;
X int shift;
X XEvent event;
X XWindowAttributes draw_wattr;
X GC draw_gc;
X Visual *draw_v;
X long save_event_mask;
X
X if (manparm.window == 0)
X return;
X manparm.lx = manparm.zoom->lx;
X manparm.ly = manparm.zoom->ly;
X manparm.ux = manparm.zoom->ux;
X manparm.uy = manparm.zoom->uy;
X update_coordinates (&manparm, 1);
X
X XGetWindowAttributes (display, manparm.window, &draw_wattr);
X draw_gc = screen->default_gc;
X draw_v = screen->root_visual;
X save_event_mask = draw_wattr.your_event_mask;
X if (manparm.pixwidth != draw_wattr.width || manparm.pixheight != draw_wattr.height)
X {
X /* screen dimension changed. rebuild image line information */
X
X manparm.pixheight = draw_wattr.height;
X manparm.pixwidth = draw_wattr.width;
X manparm.bytewidth = (manparm.pixwidth + dots_per_byte - 1) / dots_per_byte;
X scanline = -1;
X
X if (ximage)
X XDestroyImage (ximage); /* also deallocates image_data automagically */
X if (manparm.pix)
X free (manparm.pix);
X
X image_data = malloc (manparm.bytewidth + 1); /* Really! bug in ISC X11?? */
X manparm.pix = (unsigned char *) malloc (manparm.bytewidth * manparm.pixheight);
X if (image_data == NULL || manparm.pix == NULL)
X { printf ("malloc failed\n");
X return;
X }
X ximage = XCreateImage (display, draw_v, depth, ZPixmap, 0, image_data, manparm.pixwidth, 1, 8, 0);
X ximage->byte_order = MSBFirst;
X ximage->bitmap_bit_order = MSBFirst;
X }
X
X /* incremental x/y values for pixel coordinates */
X
X incrx = (manparm.zoom->ux - manparm.zoom->lx) / manparm.pixwidth;
X incry = (manparm.zoom->uy - manparm.zoom->ly) / manparm.pixheight;
X y = manparm.zoom->uy;
X
X XClearWindow (display, manparm.window);
X XSelectInput (display, manparm.window, ButtonPressMask | ButtonReleaseMask | ExposureMask);
X
X for (iy = 0; iy < draw_wattr.height; iy++, y-= incry)
X { int i;
X if (depth < 8)
X for (i = 0; i < manparm.bytewidth; i++)
X *(image_data + i) = 0;
X x = manparm.zoom->lx;
X
X /* compute colour values for each pixel in a single scan line */
X
X for (ix = 0; ix < manparm.pixwidth; ix++, x+= incrx)
X {
X /* compute set value for current point */
X
X wx = x; wy = y;
X for (i = 0; i < ITERATION_DEPTH; i++)
X { oldwx = wx;
X wx = wx * wx - wy * wy + x;
X wy = 2 * oldwx * wy + y;
X if (wx * wx + wy * wy > 4)
X goto useit;
X }
X if (depth == 8)
X { if (INFINITY_COLOR >= 0)
X i = INFINITY_COLOR - COLOR_BIAS;
X }
X else
X { if (INFINITY_COLOR >= 0)
X i = INFINITY_COLOR;
X }
X
useit: /* assign colour to pixel */
X
X switch (depth)
X {
X case 8:
X image_data[ix] = i + COLOR_BIAS;
X break;
X
X case 4:
X if (ix % 2)
X image_data[ix >> 1] |= (i % 16);
X else
X image_data[ix >> 1] |= ((i % 16) << 4);
X break;
X
X case 2:
X switch (ix % 4)
X {
X case 0: shift = 6; break;
X case 1: shift = 4; break;
X case 2: shift = 2; break;
X case 3: shift = 0; break;
X }
X image_data[ix >> 2] |= (i % 4) << shift;
X break;
X
X case 1:
X if (i % 2)
X image_data[ix >> 3] |= 1 << (7 - ix%8);
X }
X }
X
X /* save scan line for exposure events or gif output */
X
X memcpy (manparm.pix + iy * manparm.bytewidth, image_data, manparm.bytewidth);
X scanline = iy;
X
X /* send image line to screen */
X
X XPutImage (display, manparm.window, draw_gc, ximage, 0,0, 0, iy, manparm.pixwidth, 1);
X
X /* check for exposure or buttons after a few lines have been drawn.
X This keeps server queries do a reasonable level while still
X allowing exposures without too much delay.
X */
X if (iy % EXPOSURE_TEST == 0)
X { /* XSync to ensure exposure or button is honoured "fast" */
X
X XSync (display, False);
X
X /* first cleanup any pending exposures */
X
X while (XCheckTypedEvent (display, Expose, &event) == True)
X XtDispatchEvent (&event);
X
X /* then check for abort if a button is pressed */
X
X while (XCheckWindowEvent (display, manparm.window, ButtonPressMask | ButtonReleaseMask, &event) == True)
X { if (event.type == ButtonRelease)
X goto escape;
X }
X }
X }
escape:
X XSelectInput (display, manparm.window, save_event_mask);
}
X
/************************************************************************
* expose_mandel() handle mandel exposure event *
************************************************************************/
X
void expose_mandel (w, unused, event)
Widget w;
caddr_t unused;
XXExposeEvent *event;
{
X if (manparm.window == 0)
X return;
X if (event && manparm.pix && scanline >= 0)
X redraw_mandel (event);
}
X
/************************************************************************
* redraw_mandel() reshow mandelbrot from backup image. *
************************************************************************/
X
void redraw_mandel (event)
XXExposeEvent *event;
{
X int iy;
X XWindowAttributes draw_wattr;
X GC draw_gc;
X Visual *draw_v;
X int maxy;
X
X if (manparm.window == 0)
X return;
X XGetWindowAttributes (display, manparm.window, &draw_wattr);
X draw_gc = screen->default_gc;
X draw_v = screen->root_visual;
X if (event == NULL)
X {
X /* refresh entire window */
X
X maxy = MIN (scanline, manparm.pixheight-1);
X for (iy = 0; iy <= maxy; iy++)
X { memcpy (image_data, manparm.pix + iy * manparm.bytewidth, manparm.bytewidth);
X XPutImage (display, manparm.window, draw_gc, ximage, 0,0, 0, iy, manparm.pixwidth, 1);
X }
X }
X else if (event->x < manparm.pixwidth)
X {
X /* refresh only exposed area */
X
X int first_byte, last_byte, nbytes, first_dot, last_dot, ndots;
X
X if (event->x < manparm.pixwidth)
X { first_byte = event->x / dots_per_byte;
X first_dot = first_byte * dots_per_byte;
X last_dot = MIN (manparm.pixwidth - 1, event->x + event->width - 1);
X last_byte = (last_dot + dots_per_byte - 1) / dots_per_byte;
X nbytes = last_byte - first_byte + 1;
X ndots = last_dot - first_dot + 1;
X maxy = MIN (event->y + event->height, manparm.pixheight);
X for (iy = event->y; iy < maxy && iy <= scanline; iy++)
X { memcpy (image_data, manparm.pix + iy * manparm.bytewidth + first_byte, nbytes);
X XPutImage (display, manparm.window, draw_gc, ximage, 0,0, event->x, iy, ndots, 1);
X }
X }
X }
X
X XFlush(display);
}
X
/************************************************************************
* do_zoom () button: zomm zoom into mandelbrot *
* The rubber band preserves preserves the current *
* window aspect ration. *
************************************************************************/
X
void do_zoom (w, client_data, call_data)
Widget w;
caddr_t client_data;
caddr_t call_data;
{
X XWindowAttributes draw_wattr;
X GC draw_gc;
X Window Root;
X int S;
X int hh, ww, delta;
X double scaley, xa, ya, xb, yb;
X long save_event_mask;
X int have_press;
X
X Window root, child;
X int pos_x, pos_y;
X unsigned int keys_buttons;
X int root_x, root_y;
X
X if (activeimage->window == 0)
X return;
X if (activeimage->zoom == NULL) return;
X
X draw_gc = screen->default_gc;
X S = DefaultScreen (display);
X Root = RootWindow (display, S);
X
X XSetForeground (display, draw_gc, 255);
X XSetSubwindowMode (display, draw_gc, IncludeInferiors);
X XSetFunction (display, draw_gc, GXxor);
X
X XGetWindowAttributes (display, activeimage->window, &draw_wattr);
X
X save_event_mask = draw_wattr.your_event_mask;
X XSelectInput (display, activeimage->window, ButtonPressMask | ButtonReleaseMask
X | PointerMotionHintMask | PointerMotionMask);
X
X have_press = 0; /* Motif translation override may cause a */
X /* button release BEFORE a button press */
X while (1)
X { static int rubberband = 1;
X XEvent report;
X
X XNextEvent (display, &report);
X if (report.xbutton.window != activeimage->window)
X continue;
X switch(report.type)
X {
X int winx0,winy0,winx1,winy1,width,height;
X int x0, y0, x1, y1;
X double tw, th;
X
X case ButtonPress:
X if (report.xbutton.button != Button1)
X break;
X x0 = winx0 = report.xbutton.x;
X y0 = winy0 = report.xbutton.y;
X rubberband = 0;
X width = height = 0;
X have_press = 1;
X break;
X
X case ButtonRelease:
X if (have_press == 0)
X break;
X winx1 = report.xbutton.x;
X winy1 = report.xbutton.y;
X x0 = MIN (winx0, winx1);
X x1 = MAX (winx0, winx1);
X y0 = MIN (winy0, winy1);
X y1 = MAX (winy0, winy1);
X width = x1 - x0;
X height = y1 - y0;
X
X /* ensure rubber band preserves the proportions of the
X current window.
X */
X ww = width;
X hh = height;
X delta = MAX (ww, hh);
X scaley = (double) (draw_wattr.height) / (double) (draw_wattr.width);
X x1 = x0 + delta;
X y1 = y0 + delta * scaley;
X height = y1 - y0;
X width = x1 - x0;
X
X XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
X rubberband = 1;
X XSetFunction (display, draw_gc, GXcopy);
X XFlush (display);
X if (delta > 5 && report.xbutton.button == 1)
X { tw = activeimage->zoom->ux - activeimage->zoom->lx;
X th = activeimage->zoom->uy - activeimage->zoom->ly;
X zoomtmp = (struct zoomd *) malloc (sizeof (struct zoomd));
X zoomtmp->zp = activeimage->zoom; /* push onto stack */
X zoomtmp->ux = activeimage->zoom->lx + ((double) x1 / (double) activeimage->pixwidth) * tw;
X zoomtmp->lx = activeimage->zoom->lx + ((double) x0 / (double) activeimage->pixwidth) * tw;
X zoomtmp->ly = activeimage->zoom->uy - ((double) y1 / (double) activeimage->pixheight) * th;
X zoomtmp->uy = activeimage->zoom->uy - ((double) y0 / (double) activeimage->pixheight) * th;
X activeimage->zoom = zoomtmp; /* activeimage->zoom is current pointer */
X XSelectInput (display, activeimage->window, save_event_mask);
X if (activeimage == &manparm)
X mandel ();
X else
X julia (0, 0);
X }
X else
X { /* too small image or pressing button 2/3 quits zoom */
X
X activeimage->lx = activeimage->zoom->lx;
X activeimage->ly = activeimage->zoom->ly;
X activeimage->ux = activeimage->zoom->ux;
X activeimage->uy = activeimage->zoom->uy;
#ifndef MOTIF
X printf ("\n");
#else
X update_coordinates (activeimage, 0);
#endif
X XSelectInput (display, activeimage->window, save_event_mask);
X }
X return;
X
X case MotionNotify:
X if (!XQueryPointer (display, report.xmotion.window,
X &root, &child, &root_x, &root_y,
X &pos_x, &pos_y, &keys_buttons))
X break;
X winx1 = pos_x;
X winy1 = pos_y;
X if (rubberband == 0)
X { XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
X x0 = MIN(winx0, winx1);
X x1 = MAX(winx0, winx1);
X y0 = MIN(winy0, winy1);
X y1 = MAX(winy0, winy1);
X width = x1 - x0;
X height = y1 - y0;
X
X /* ensure rubber band preserves the proportions of the
X current window.
X */
X ww = width;
X hh = height;
X delta = MAX (ww, hh);
X scaley = (double) (draw_wattr.height) / (double) (draw_wattr.width);
X x1 = x0 + delta;
X y1 = y0 + delta * scaley;
X height = y1 - y0;
X width = x1 - x0;
X
X XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
X
X tw = activeimage->zoom->ux - activeimage->zoom->lx;
X th = activeimage->zoom->uy - activeimage->zoom->ly;
X xa = activeimage->zoom->lx + ((double) x0 / (double) activeimage->pixwidth) * tw;
X ya = activeimage->zoom->uy - ((double) y0 / (double) activeimage->pixheight) * th;
X xb = activeimage->zoom->lx + ((double) x1 / (double) activeimage->pixwidth) * tw;
X yb = activeimage->zoom->uy - ((double) y1 / (double) activeimage->pixheight) * th;
X
X activeimage->lx = MIN (xa, xb);
X activeimage->ly = MIN (ya, yb);
X activeimage->ux = MAX (xa, xb);
X activeimage->uy = MAX (ya, yb);
X update_coordinates (activeimage, 0);
X }
X else
X {
X tw = activeimage->zoom->ux - activeimage->zoom->lx;
X th = activeimage->zoom->uy - activeimage->zoom->ly;
X xa = activeimage->zoom->lx + ((double) winx1 / (double) activeimage->pixwidth) * tw;
X ya = activeimage->zoom->uy - ((double) winy1 / (double) activeimage->pixheight) * th;
X
X activeimage->pcolour = pixel_colour (activeimage, winx1, winy1);
X activeimage->px = xa;
X activeimage->py = ya;
X update_point (activeimage);
X }
X fflush (stdout);
X XFlush (display);
X break;
X
X default:
X break;
X }
X }
}
X
/************************************************************************
* do_unzoom() button: unzoom recalc previous zoom level. *
************************************************************************/
X
void do_unzoom (w, client_data, call_data)
Widget w;
caddr_t client_data;
caddr_t call_data;
{
X if (activeimage->window == 0)
X return;
X if (activeimage->zoom)
X { /* selecting mooz before mandel invalid */
X if (zoomtmp = activeimage->zoom->zp)
X { /* last on stack */
X free(activeimage->zoom);
X activeimage->zoom = zoomtmp;
X }
X else
X return;
X if (activeimage == &manparm)
X mandel ();
X else
X julia (0, 0);
X }
}
X
/************************************************************************
* pixel_colour() return the colour of a pixel *
************************************************************************/
X
int pixel_colour (p, ix, iy)
struct imageparm *p;
int ix, iy;
{ int colour, shift;
X unsigned char *imageline;
X
X imageline = p->pix + iy * p->bytewidth;
X switch (depth)
X {
X case 8:
X colour = imageline[ix] & 0x0ff;
X break;
X
X case 4:
X if (ix % 2)
X shift = 0;
X else
X shift = 4;
X colour = (imageline[ix >> 1] >> shift) & 0x0f;
X break;
X
X case 2:
X switch (ix % 4)
X {
X case 0: shift = 6; break;
X case 1: shift = 4; break;
X case 2: shift = 2; break;
X case 3: shift = 0; break;
X }
X colour = (imageline[ix >> 2] >> shift) & 0x03;
X break;
X
X case 1:
X colour = (imageline[ix >> 3] >> (7 - ix % 8)) & 0x01;
X }
X return (colour);
}
SHAR_EOF
echo 'File mandel.c is complete' &&
chmod 0644 mandel.c ||
echo 'restore of mandel.c failed'
Wc_c="`wc -c < 'mandel.c'`"
test 15435 -eq "$Wc_c" ||
echo 'mandel.c: original size 15435, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= mandel.h ==============
if test -f 'mandel.h' -a X"$1" != X"-c"; then
echo 'x - skipping mandel.h (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting mandel.h (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'mandel.h' &&
/* ta=4 */
/* xmandel.h */
X
/* ---- some changes you may wish to make ------- */
X
/* memcpy(dest,src,nbytes) is used in various routines. If memcpy()
X is not available, use the #define for bcopy(). If bcopy() is not
X available then enable "NEEDMEMCPY" to use a very inefficient
X memory copy.
*/
X
#ifdef HAVEBCOPY
#define memcpy(a,b,c) bcopy(b,a,c) /* bsd type */
#endif
X
/* #define NEEDMEMCPY /* for systems with neither */
X
X
/* set maximum depth of iteration for mandelbrot and julia sets. */
X
#define ITERATION_DEPTH 256
X
/* Check for exposure events after this many scan lines have been drawn
X by the Mandelbrot or Julia generator. If you have a very large
X ITERATION_DEPTH (e.g. > 400) an EXPOSURE_TEST of 1 or 2 is reasonable */
X
#define EXPOSURE_TEST 4
X
/* If a 256 colour display is used, Set a "color bias" to offset into
X the colour table for colour value 0. Iterations arc coloured
X as "iteration_count + COLOR_BIAS".
*/
X
#define COLOR_BIAS 16
X
/* Set a color value for INFINITY. A value >= 0 assigns the specified
X colour number. A value < 0 uses the "default" colour.
*/
X
#define INFINITY_COLOR -1
X
/* Initial starting coordinates for mandelbrot set */
X
#define START_LX -2.25
#define START_UX 1.0
#define START_LY -1.5
#define START_UY 1.5
X
X
/* ----- end configuration ------- */
X
#define MIN(a,b)((a) < (b) ? (a) : (b))
#define MAX(a,b)((a) < (b) ? (b) : (a))
#define ABS(a) ((a) < 0 ? (-a) : (a))
X
/* for those places where I forgot to make the change... */
X
#define malloc(x) XtMalloc(x)
#define calloc(x,y) XtCalloc(x,y)
#define free(x) XtFree(x)
X
typedef unsigned char byte;
X
struct zoomd
{ struct zoomd *zp; /* previous zoom pointer */
X double lx, ux; /* bounds for zoom */
X double ly, uy;
};
X
#define SAVESIZE 25
X
struct imageparm
{ Window window; /* image in this window */
X double lx, ly, ux, uy; /* image corner coordinates. */
X double px, py; /* point location (for julia) */
X int rotation; /* current colour rotation */
X int totrot; /* total rotation count */
X int pcolour; /* pixel colour */
X long pixheight; /* image height in pixels */
X long pixwidth; /* impage width in pixels */
X long bytewidth; /* width of image line in bytes */
X unsigned char *pix; /* copy of generated image */
X struct zoomd *zoom; /* zoom stack pointer */
X char sux[SAVESIZE]; /* text ux, uy etc. to detect */
X char suy[SAVESIZE]; /* if user changed values. */
X char slx[SAVESIZE];
X char sly[SAVESIZE];
} ;
X
struct enter_buttons
{ char *button; /* label text */
X int bx; /* lable x */
X int by; /* label y */
X char *field; /* data field name */
X int fsize; /* data field size chars */
} ;
X
X
struct button_list
{ char *ident; /* widget name */
X void (*bcall)(); /* callback function */
X int x; /* x column location */
X int y; /* y row location */
} ;
X
X
#ifdef __STDC__
/* main.c */
int main(int argc, char **argv);
void update_coordinates(struct imageparm *image, int lf);
void update_point(struct imageparm *image);
/* mandel.c */
void start_mandel(void);
void redo_mandel(void);
void expose_mandel(Widget w, caddr_t unused, XExposeEvent *event);
void redraw_mandel(XExposeEvent *event);
void do_zoom(Widget w, caddr_t client_data, caddr_t call_data);
void do_unzoom(Widget w, caddr_t client_data, caddr_t call_data);
int pixel_colour(struct imageparm *p, int ix, int iy);
/* julia.c */
void start_julia(int destroy_pixmap, int newimage);
void julia(int destroy_pixmap, int newimage);
void expose_julia(Widget w, caddr_t unused, XExposeEvent *event);
void redraw_julia(XExposeEvent *event);
/* writegif.c */
void ws1te_gif_image(char *fname, struct imageparm *imageinfo);
#else
/* main.c */
int main();
void update_coordinates();
void update_point();
/* mandel.c */
void start_mandel();
void redo_mandel();
void expose_mandel();
void redraw_mandel();
void do_zoom();
void do_unzoom();
int pixel_colour();
/* julia.c */
void start_julia();
void julia();
void expose_julia();
void redraw_julia();
/* writegif.c */
void write_gif_image();
#endif
SHAR_EOF
chmod 0644 mandel.h ||
echo 'restore of mandel.h failed'
Wc_c="`wc -c < 'mandel.h'`"
test 4079 -eq "$Wc_c" ||
echo 'mandel.h: original size 4079, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= writegif.c ==============
if test -f 'writegif.c' -a X"$1" != X"-c"; then
echo 'x - skipping writegif.c (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting writegif.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'writegif.c' &&
/* ta=4 */
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Shell.h>
#include "mandel.h"
X
#define MAX_COLORS 3
X
unsigned char rmap[256], gmap[256], bmap[256];
static struct imageparm *image;
extern Display *display;
X
extern int depth;
typedef long int count_int;
X
#ifdef __STDC__
static int getcolors(void);
static int writegif(FILE *fp, byte *pic, int w, int h, byte *rmap, byte *gmap, byte *bmap, int numcols, int colorstyle);
static void putword(int w, FILE *fp);
static void compress(int init_bits, FILE *outfile, byte *data, int len);
static void output(int code);
static void cl_block(void);
static void cl_hash(register count_int hsize);
static void char_init(void);
static void char_out(int c);
static void flush_char(void);
#else
static int getcolors();
static int writegif();
static void putword();
static void compress();
static void output();
static void cl_block();
static void cl_hash();
static void char_init();
static void char_out();
static void flush_char();
#endif
X
/************************************************************************
* write_gif () *
* X11 image data recorded in *image->pix has pixel colors comressed *
* to adjacent bits. If there are less than 8 bits per pixel, unpack *
* the bytes - GIF format must have one pixel per output byte. *
* After compression, the wasted space is obviously removed. *
************************************************************************/
X
void write_gif_image (fname, imageinfo)
char *fname;
struct imageparm *imageinfo;
{ FILE *fp;
X int i;
X int ncolors;
X int ix, iy, shift;
X byte *bytes, *these_bits, *input, *output;
X
X image = imageinfo;
X if (image->pix == NULL)
X return;
X
X for (i = 0; i < 256; i++)
X rmap[i] = gmap[i] = bmap[i] = 0;
X
X fp = fopen (fname, "w");
X if (fp == NULL)
X { printf ("Cannot open gif output file\n");
X exit (0);
X }
X ncolors = getcolors();
X if (depth != 8)
X { bytes = (byte *) malloc (image->pixheight * image->pixwidth);
X for (iy = 0; iy < image->pixheight; iy++)
X {
X output = bytes + iy * image->pixwidth;
X input = image->pix + iy * image->bytewidth;
X switch (depth)
X {
X case 4:
X for (ix = 0; ix < image->pixwidth; ix++)
X { if (ix % 2)
X shift = 0;
X else
X shift = 4;
X output[ix] = (input[ix >> 1] >> shift) & 0x0f;
X }
X break;
X
X case 2:
X for (ix = 0; ix < image->pixwidth; ix++)
X { switch (ix % 4)
X {
X case 0: shift = 6; break;
X case 1: shift = 4; break;
X case 2: shift = 2; break;
X case 3: shift = 0; break;
X }
X output[ix] = (input[ix >> 2] >> shift) & 0x03;
X }
X break;
X
X case 1:
X for (ix = 0; ix < image->pixwidth; ix++)
X output[ix] = (input[ix >> 3] >> (7 - ix % 8)) & 0x01;
X }
X }
X these_bits = bytes;
X }
X else
X { these_bits = image->pix;
X bytes = NULL;
X }
X writegif (fp, these_bits, image->pixwidth, image->pixheight, rmap, gmap, bmap, ncolors, 0);
X if (bytes)
X free (bytes);
X fclose (fp);
}
X
/************************************************************************
* getcolors () get current colour map in rgb for gif output *
************************************************************************/
X
static int getcolors ()
{
X Colormap default_cmap;
X int ncolors, i;
X XColor my_colors[256];
X
X ncolors = DisplayCells (display, DefaultScreen (display));
X default_cmap = DefaultColormap (display, DefaultScreen (display));
X for (i = 0; i < DisplayCells (display, 0); i++)
X { my_colors[i].pixel = i;
X my_colors[i].flags = DoRed | DoGreen | DoBlue;
X }
X
X XQueryColors (display, default_cmap, my_colors, ncolors);
X
X /* scale the colours to a 0..255 range as expected by GIF
X X11 always gives RGB values as a 16 bit number.
X */
X for (i = 0; i < ncolors; i++)
X { rmap[i] = (double) my_colors[i].red / 256.0;
X gmap[i] = (double) my_colors[i].green / 256.0;
X bmap[i] = (double) my_colors[i].blue / 256.0;
X }
X return (ncolors);
}
X
X
/* Extracted for the XV.2.11 source distribution....
X *
X * xvgifwr.c - handles writing of GIF files. based on flgife.c and
X * flgifc.c from the FBM Library, by Michael Maudlin
X *
X * Contains:
X * WriteGIF(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
X *
X * Note: slightly brain-damaged, in that it'll only write non-interlaced
X * GIF files (in the interests of speed, or something)
X *
X */
X
X
X
/*****************************************************************
X * Portions of this code Copyright (C) 1989 by Michael Mauldin.
X * Permission is granted to use this file in whole or in part provided
X * that you do not sell it for profit and that this copyright notice
X * and the names of all authors are retained unchanged.
X *
X * Authors: Michael Mauldin (mlm@cs.cmu.edu)
X * David Rowley (mgardi@watdcsu.waterloo.edu)
X *
X * Based on: compress.c - File compression ala IEEE Computer, June 1984.
X *
X * Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
X * Jim McKie (decvax!mcvax!jim)
X * Steve Davies (decvax!vax135!petsd!peora!srd)
X * Ken Turkowski (decvax!decwrl!turtlevax!ken)
X * James A. Woods (decvax!ihnp4!ames!jaw)
X * Joe Orost (decvax!vax135!petsd!joe)
X *****************************************************************/
X
/*
X * Copyright 1989, 1990 by the University of Pennsylvania
X *
X * Permission to use, copy, and distribute for non-commercial purposes,
X * is hereby granted without fee, providing that the above copyright
X * notice appear in all copies and that both the copyright notice and this
X * permission notice appear in supporting documentation.
X *
X * The software may be modified for your own purposes, but modified versions
X * may not be distributed.
X *
X * This software is provided "as is" without any express or implied warranty.
X */
X
X
/* MONO returns total intensity of r,g,b components */
X
#define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5) /*.33R+ .5G+ .17B*/
X
int DEBUG = 0;
X
static int Width, Height;
static int curx, cury;
static long CountDown;
static int Interlace;
static byte bw[2] = {0, 0xff};
X
/*************************************************************/
static int writegif (fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
FILE *fp;
byte *pic;
int w,h;
byte *rmap, *gmap, *bmap;
int numcols, colorstyle;
{
X int RWidth, RHeight;
X int LeftOfs, TopOfs;
X int Resolution, ColorMapSize, InitCodeSize, Background, BitsPerPixel;
X int i,j;
X
X
X /* if writing B/W stipple... */
X if (colorstyle==2) {
X rmap = gmap = bmap = bw;
X numcols = 2;
X }
X
X Interlace = 0;
X Background = 0;
X
X /* figure out 'BitsPerPixel' */
X for (i=1; i<8; i++)
X if ( (1<<i) >= numcols) break;
X
X BitsPerPixel = i;
X
X ColorMapSize = 1 << BitsPerPixel;
X
X RWidth = Width = w;
X RHeight = Height = h;
X LeftOfs = TopOfs = 0;
X
X Resolution = BitsPerPixel;
X
X CountDown = w * h; /* # of pixels we'll be doing */
X
X if (BitsPerPixel <= 1) InitCodeSize = 2;
X else InitCodeSize = BitsPerPixel;
X
X curx = cury = 0;
X
X if (!fp) {
X fprintf(stderr, "WriteGIF: file not open for writing\n" );
X return (1);
X }
X
X if (DEBUG)
X fprintf(stderr,"WrGIF: pic=%lx, w,h=%dx%d, numcols=%d, Bits%d,Cmap=%d\n",
X pic, w,h,numcols,BitsPerPixel,ColorMapSize);
X
X fwrite("GIF87a", 1, 6, fp); /* the GIF magic number */
X
X putword(RWidth, fp); /* screen descriptor */
X putword(RHeight, fp);
X
X i = 0x80; /* Yes, there is a color map */
X i |= (8-1)<<4; /* OR in the color resolution (hardwired 8) */
X i |= (BitsPerPixel - 1); /* OR in the # of bits per pixel */
X fputc(i,fp);
X
X fputc(Background, fp); /* background color */
X
X fputc(0, fp); /* future expansion byte */
X
X
X if (colorstyle == 1) { /* greyscale */
X for (i=0; i<ColorMapSize; i++) {
X j = MONO(rmap[i], gmap[i], bmap[i]);
X fputc(j, fp);
X fputc(j, fp);
X fputc(j, fp);
X }
X }
X else {
X for (i=0; i<ColorMapSize; i++) { /* write out Global colormap */
X fputc(rmap[i], fp);
X fputc(gmap[i], fp);
X fputc(bmap[i], fp);
X }
X }
X
X fputc( ',', fp ); /* image separator */
X
X /* Write the Image header */
X putword(LeftOfs, fp);
X putword(TopOfs, fp);
X putword(Width, fp);
X putword(Height, fp);
X if (Interlace) fputc(0x40, fp); /* Use Global Colormap, maybe Interlace */
X else fputc(0x00, fp);
X
X fputc(InitCodeSize, fp);
X compress(InitCodeSize+1, fp, pic, w*h);
X
X fputc(0,fp); /* Write out a Zero-length packet (EOF) */
X fputc(';',fp); /* Write GIF file terminator */
X
X return (0);
}
X
X
X
X
/******************************/
static void putword(w, fp)
int w;
FILE *fp;
{
X /* writes a 16-bit integer in GIF order (LSB first) */
X fputc(w & 0xff, fp);
X fputc((w>>8)&0xff, fp);
}
X
X
X
X
/***********************************************************************/
X
X
static unsigned long cur_accum = 0;
static int cur_bits = 0;
X
X
X
X
#define min(a,b) ((a>b) ? b : a)
X
#define BITS 12
#define MSDOS 1
X
#define HSIZE 5003 /* 80% occupancy */
X
typedef unsigned char char_type;
X
X
static int n_bits; /* number of bits/code */
static int maxbits = BITS; /* user settable max # bits/code */
static int maxcode; /* maximum code, given n_bits */
static int maxmaxcode = 1 << BITS; /* NEVER generate this */
X
#define MAXCODE(n_bits) ( (1 << (n_bits)) - 1)
X
static count_int htab [HSIZE];
static unsigned short codetab [HSIZE];
#define HashTabOf(i) htab[i]
#define CodeTabOf(i) codetab[i]
X
static int hsize = HSIZE; /* for dynamic table sizing */
X
/*
X * To save much memory, we overlay the table used by compress() with those
X * used by decompress(). The tab_prefix table is the same size and type
X * as the codetab. The tab_suffix table needs 2**BITS characters. We
X * get this from the beginning of htab. The output stack uses the rest
X * of htab, and contains characters. There is plenty of room for any
X * possible stack (stack used to be 8000 characters).
X */
X
#define tab_prefixof(i) CodeTabOf(i)
#define tab_suffixof(i) ((char_type *)(htab))[i]
#define de_stack ((char_type *)&tab_suffixof(1<<BITS))
X
static int free_ent = 0; /* first unused entry */
X
/*
X * block compression parameters -- after all codes are used up,
X * and compression rate changes, start over.
X */
static int clear_flg = 0;
X
static long int in_count = 1; /* length of input */
static long int out_count = 0; /* # of codes output (for debugging) */
X
/*
X * compress stdin to stdout
X *
X * Algorithm: use open addressing double hashing (no chaining) on the
X * prefix code / next character combination. We do a variant of Knuth's
X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
X * secondary probe. Here, the modular division first probe is gives way
X * to a faster exclusive-or manipulation. Also do block compression with
X * an adaptive reset, whereby the code table is cleared when the compression
X * ratio decreases, but after the table fills. The variable-length output
X * codes are re-sized at this point, and a special CLEAR code is generated
X * for the decompressor. Late addition: construct the table according to
X * file size for noticeable speed improvement on small files. Please direct
X * questions about this implementation to ames!jaw.
X */
X
static int g_init_bits;
static FILE *g_outfile;
X
static int ClearCode;
static int EOFCode;
X
X
/********************************************************/
static void compress(init_bits, outfile, data, len)
int init_bits;
FILE *outfile;
byte *data;
int len;
{
X register long fcode;
X register int i = 0;
X register int c;
X register int ent;
X register int disp;
X register int hsize_reg;
X register int hshift;
X
X /*
X * Set up the globals: g_init_bits - initial number of bits
X * g_outfile - pointer to output file
X */
X g_init_bits = init_bits;
X g_outfile = outfile;
X
X /* initialize 'compress' globals */
X maxbits = BITS;
X maxmaxcode = 1<<BITS;
X memset((char *) htab, 0, sizeof(htab));
X memset((char *) codetab, 0, sizeof(codetab));
X hsize = HSIZE;
X free_ent = 0;
X clear_flg = 0;
X in_count = 1;
X out_count = 0;
X cur_accum = 0;
X cur_bits = 0;
X
X
X /*
X * Set up the necessary values
X */
X out_count = 0;
X clear_flg = 0;
X in_count = 1;
X maxcode = MAXCODE(n_bits = g_init_bits);
X
X ClearCode = (1 << (init_bits - 1));
X EOFCode = ClearCode + 1;
X free_ent = ClearCode + 2;
X
X char_init();
X ent = *data++; len--;
X
X hshift = 0;
X for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
X hshift++;
X hshift = 8 - hshift; /* set hash code range bound */
X
X hsize_reg = hsize;
X cl_hash( (count_int) hsize_reg); /* clear hash table */
X
X output(ClearCode);
X
X while (len) {
X c = *data++; len--;
X in_count++;
X
X fcode = (long) ( ( (long) c << maxbits) + ent);
X i = (((int) c << hshift) ^ ent); /* xor hashing */
X
X if ( HashTabOf (i) == fcode ) {
X ent = CodeTabOf (i);
X continue;
X }
X
X else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
X goto nomatch;
X
X disp = hsize_reg - i; /* secondary hash (after G. Knott) */
X if ( i == 0 )
X disp = 1;
X
probe:
X if ( (i -= disp) < 0 )
X i += hsize_reg;
X
X if ( HashTabOf (i) == fcode ) {
X ent = CodeTabOf (i);
X continue;
X }
X
X if ( (long)HashTabOf (i) > 0 )
X goto probe;
X
nomatch:
X output(ent);
X out_count++;
X ent = c;
X
X if ( free_ent < maxmaxcode ) {
X CodeTabOf (i) = free_ent++; /* code -> hashtable */
X HashTabOf (i) = fcode;
X }
X else
X cl_block();
X }
X
X /* Put out the final code */
X output(ent);
X out_count++;
X output(EOFCode);
}
X
X
/*****************************************************************
X * TAG( output )
X *
X * Output the given code.
X * Inputs:
X * code: A n_bits-bit integer. If == -1, then EOF. This assumes
X * that n_bits =< (long)wordsize - 1.
X * Outputs:
X * Outputs code to the file.
X * Assumptions:
X * Chars are 8 bits long.
X * Algorithm:
X * Maintain a BITS character long buffer (so that 8 codes will
X * fit in it exactly). Use the VAX insv instruction to insert each
X * code in turn. When the buffer fills up empty it and start over.
X */
X
static
unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
X 0x001F, 0x003F, 0x007F, 0x00FF,
X 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
X 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
X
static void output(code)
int code;
{
X cur_accum &= masks[cur_bits];
X
X if (cur_bits > 0)
X cur_accum |= ((long)code << cur_bits);
X else
X cur_accum = code;
X
X cur_bits += n_bits;
X
X while( cur_bits >= 8 ) {
X char_out( (unsigned int) (cur_accum & 0xff) );
X cur_accum >>= 8;
X cur_bits -= 8;
X }
X
X /*
X * If the next entry is going to be too big for the code size,
X * then increase it, if possible.
X */
X
X if (free_ent > maxcode || clear_flg) {
X
X if( clear_flg ) {
X maxcode = MAXCODE (n_bits = g_init_bits);
X clear_flg = 0;
X }
X else {
X n_bits++;
X if ( n_bits == maxbits )
X maxcode = maxmaxcode;
X else
X maxcode = MAXCODE(n_bits);
X }
X }
X
X if( code == EOFCode ) {
X /* At EOF, write the rest of the buffer */
X while( cur_bits > 0 ) {
X char_out( (unsigned int)(cur_accum & 0xff) );
X cur_accum >>= 8;
X cur_bits -= 8;
X }
X
X flush_char();
X
X fflush( g_outfile );
X
X if( ferror( g_outfile ) )
X { printf ("unable to write GIF file\n");
X exit (1);
X }
X }
}
X
X
/********************************/
static void cl_block () /* table clear for block compress */
{
X /* Clear out the hash table */
X
X cl_hash ( (count_int) hsize );
X free_ent = ClearCode + 2;
X clear_flg = 1;
X
X output(ClearCode);
}
X
X
/********************************/
static void cl_hash(hsize) /* reset code table */
register count_int hsize;
{
X register count_int *htab_p = htab+hsize;
X register long i;
X register long m1 = -1;
X
X i = hsize - 16;
X do { /* might use Sys V memset(3) here */
X *(htab_p-16) = m1;
X *(htab_p-15) = m1;
X *(htab_p-14) = m1;
X *(htab_p-13) = m1;
X *(htab_p-12) = m1;
X *(htab_p-11) = m1;
X *(htab_p-10) = m1;
X *(htab_p-9) = m1;
X *(htab_p-8) = m1;
X *(htab_p-7) = m1;
X *(htab_p-6) = m1;
X *(htab_p-5) = m1;
X *(htab_p-4) = m1;
X *(htab_p-3) = m1;
X *(htab_p-2) = m1;
X *(htab_p-1) = m1;
X htab_p -= 16;
X } while ((i -= 16) >= 0);
X
X for ( i += 16; i > 0; i-- )
X *--htab_p = m1;
}
X
X
/******************************************************************************
X *
X * GIF Specific routines
X *
X ******************************************************************************/
X
/*
X * Number of characters so far in this 'packet'
X */
static int a_count;
X
/*
X * Set up the 'byte output' routine
X */
static void char_init()
{
X a_count = 0;
}
X
/*
X * Define the storage for the packet accumulator
X */
static char accum[ 256 ];
X
/*
X * Add a character to the end of the current packet, and if it is 254
X * characters, flush the packet to disk.
X */
static void char_out(c)
int c;
{
X accum[ a_count++ ] = c;
X if( a_count >= 254 )
X flush_char();
}
X
/*
X * Flush the packet to disk, and reset the accumulator
X */
static void flush_char()
{
X if( a_count > 0 ) {
X fputc( a_count, g_outfile );
X fwrite( accum, 1, a_count, g_outfile );
X a_count = 0;
X }
}
SHAR_EOF
chmod 0644 writegif.c ||
echo 'restore of writegif.c failed'
Wc_c="`wc -c < 'writegif.c'`"
test 17660 -eq "$Wc_c" ||
echo 'writegif.c: original size 17660, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xmandel.man ==============
if test -f 'xmandel.man' -a X"$1" != X"-c"; then
echo 'x - skipping xmandel.man (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xmandel.man (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xmandel.man' &&
.TH XMANDEL X " 25 April 1992" "X Version 11"
.UC 4
.SH NAME
xmandel \- X11 interface to the Mandelbrot and Julia sets
.SH SYNOPSIS
xmandel [-display display]
.SH DESCRIPTION
.PP
.IR Xmandel
is a user friendly interface for generating and colouring Mandelbrot and Julia sets.
It initially comes up with with eleven or so command buttons,
which are described below, for controlling the execution.
A Mandelbrot set is drawn in the window of the initial form
when the \fImandel\fP button is selected.
A separate window is created for drawing the Julia sets.
.SH THEORY
Let z0 be a number in the complex plane (x + yi).
Choose a complex constant C.
Calculate z1 = z0 ** 2 + C.
Repeat this recursively, so that z2 = z1 ** 2 + C,
z3 = z2 ** 2 + C and so on.
z[n] will either tend to infinity or zero, depending
on its initial value and the constant C.
Specifically if the absolute value of z[n],
expressed as |z| = sqrt(x**2 + y**2) is greater than 2,
then the recursive formula will diverge.
.PP
So, to calculate a Julia set, take each point near (0,0i),
and use the formula z = z**2 + C recursively.
The Julia set is the set of points for which
z = z**2 + C would iterate indefinitely for the constant C.
Pixels, which represent numbers in the complex plane,
are set to the number of iterations before |z| exceeds 2.
This then becomes an index into the hardware colormap.
Each color then represents the number of iterations before
divergence is detected.
.PP
To calculate a Mandelbrot set, again take each point near (0,0i),
use the same formula z = z**2 + C recursively.
This time let C be the initial value of the point itself (C = z0).
Rather than having the same C for every point in the complex plane
as in Julia set calculations,
C is different for each point in the plane.
Again let the pixel value be the number of iterations
before |z| exceeds 2.
.PP
On monochrome displays, the pixel value is set to 1
if the iteration count is 64, otherwise 0.
.PP
Mandelbrot sets and Julia sets are obviously closely
related as can be seen from the similarity of their
respective formulas.
If the constant C is chosen from the interior of the
Mandelbrot set, then the Julia set calculated from that
constant C will be connected, that is have no gaps or discontinuities.
If the constant C is chosen from outside the Mandelbrot set,
the Julia set will be disconnected, more like grains of dust (Fatou clouds).
If the constant C is chosen from the border of the Mandelbrot set,
then the Julia set will be more convoluted.
Given this relationship between points in the Mandelbrot set
and the Julia set generated,
XXmandel provides user selection of the constant C
by mouse selection in the Mandelbrot window.
.SH BUTTONS
To control execution of the calculations, various buttons
are provided. The buttons are somewhat different between
the Athena Widget and Motif Widget implementations.
The buttons are:
.TP
.B mandel
Calculates a Mandelbrot set from (-2.25, -1.5) to (1.0, 1.5)
and display it in the window provided.
X
Pressing a mouse button with the cursor in
the drawing window terminates the calculations.
.TP
.B julia
Calculates a Julia set.
The user is required to select a point inside the Mandelbrot window using
the left mouse button as the constant C for the Julia set calculation.
It will open a new window if needed.
The Julia set is centered around (0,0),
going from (-1.5, -1.5) to (1.5, 1.5).
Julia set points can be selected from zoomed in Mandelbrot windows as well.
Beware of selecting points outside the Mandelbrot window.
X
Pressing a mouse button in the drawing window terminates the calculations.
.TP
.B Image
After the Mandelbrot or Julia set is generated, the
.I Image
button identifies which set is to be used for various manipluations
such as
.I zoom
or
.I +colour.
If this button is pressed, the active image toggles between "Mandel"
and "Julia" to identify the set that is to be manipulated.
X
The Motif implementation uses radio buttons for this toggle.
.TP
.B zoom
In order to zoom in on a given area in the Mandelbrot or Julia set,
a zoom button is provided.
The area to be zoomed in on is selected with the left mouse button.
Left button down begins the selection,
dragging with left button down draws a rubber banded box to show the zoom area,
and left button up begins the calculation.
You can zoom in on a zoomed in area until you reach
the limits of the precision of your hardware.
Selecting a zoom area that crosses a window border doesn't work.
X
To a certain degree, the zoom rubber banded box may be moved, enlarged
and otherwise resized by careful use of the mouse.
X
Zoom requests less than 5 pixels wide are ignored. The zoom
request may be terminated by pressing button 2 or 3 while creating
the rubber band.
X
If the Motif version is used, the zoom coordinates may be specified
in the
.I ZOOM COORDINATES
dialogue boxes. After the desired coodinates are enterd, pressing the
.I zoom
button activates the drawing.
.TP
.B unzoom
Return to previous zoom.
Note that you can zoom all the way out by selecting the \fImandel\fP button.
.TP
.B recalc
Recompute the set at the current coordinates. This is useful
to redisplay the current image after the set's window has been
resized.
X
If the Motif version is used, the coordinates for recalculation may be
modified in the
.I ZOOM COORDINATES
dialogue boxes.
.TP
.B colour
The
.I colour
button selects colour rotation value to be applied when the
.I +colour
or
.I -colour
buttons are used.
X
The "colour step" value is added to each pixel colour before redisplay.
The effectively rotates the image through the available colour map.
By default, the rotation value is set to the number of bit planes: for
an 8 bit display, the rotation value is 8; for a 2 bit display, the rotation
value is 2; etc.
X
The selected set and rotation value is "remembered" for use with the
.I \+colour
and
.I \-colour
buttons.
X
The "rotate" dialogue box in the Motif edition is used to set
the colour rotation value.
.TP
.B \+colour
The default set
is rotated in a positive sense by adding the previously
specified colour rotation value to all pixels.
X
An interesting "colour zoom" effect can be achieved by first setting the
colour rotation value to 1 and rapidly pressing the
.I \+colour
or
.I \-colour
button.
.TP
.B \-colour
The default set
is rotated in a negative sense by subtracting the previously
specified colour rotation value. In effect,
.I \-colour
undoes the effect of
.I \+colour.
.TP
.B gif
Either the Mandelbrot or Julia image may be captured to a GIF file.
The Mandelbrot image is saved in the specified file name if the
.I Mandelbrot
radio button is pressed, the Julia image is saved if the
.I Julia
radio button is pressed.
X
For the Motif implementation, the desired file name is entered
into the
.I Gif file
dialogue box. Pressing the
.I Save
button saves the default image (set by the radio buttons)
as a gif file.
.TP
.B remove
Remove the Julia set window. It will be recreated if another
Julia display is requested.
X
This button is not used in the Motif edition: the Julia set
may be removed by closing the Julia window.
.TP
.B quit
This causes \fIxmandel\fP to exit.
.SH MOTIF NOTES
The
.I default
set is selected by the radio buttons
.I mandel
or
.I julia.
The default set selection is used when the
.I recalc, \+colour,
.I \-colour,
or other buttons are pressed. For example, if the
.I julia
radio button is selected, the
.I recalc
button will recompute the Julia set. The Mandelbrot set is
unaffected.
X
The additional dialog boxes allow you to manually provide the
Mandelbrot zoom coordinates. Changes to the
.I POINT COORDINATES
are not allowed.
.SH BUGS
The system works only with 1, 2, 4, or 8 bit displays: 24 bit
display systems are not supported.
.PP
Exposure events are examined after the generation of every 4th
image scan line: there is some delay after and exposure event
before the image is actually refreshed.
.PP
XXmandel cannot manipluate the colour map.
.PP
Performance is slow on workstations,
especially workstations without floating point hardware. Alternatively,
extensive use of
.I xmandel
may justify the purchase of a more powerful system.
.SH AUTHOR
John L. Freeman (jlf@cray.com)
.nf
X
Changes for gif, Motif and SysV X11-R4:
X Tony Field (tony@ajfcal.cuc.ab.ca)
.fi
SHAR_EOF
chmod 0644 xmandel.man ||
echo 'restore of xmandel.man failed'
Wc_c="`wc -c < 'xmandel.man'`"
test 8293 -eq "$Wc_c" ||
echo 'xmandel.man: original size 8293, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
# ============= xmandel.mot.ad ==============
if test -f 'xmandel.mot.ad' -a X"$1" != X"-c"; then
echo 'x - skipping xmandel.mot.ad (File already exists)'
rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting xmandel.mot.ad (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'xmandel.mot.ad' &&
! Translate buttons so that they remain depressed duing the
! course of calculations or processing.
X
xmandel.name.mandel.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.julia.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.recalc.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.unzoom.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.+colour.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.-colour.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.Save.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
X
xmandel.name.zoom.Translations: #override \
X <Btn1Down>: Arm() \n \
X <Btn1Up>: ArmAndActivate()
SHAR_EOF
chmod 0644 xmandel.mot.ad ||
echo 'restore of xmandel.mot.ad failed'
Wc_c="`wc -c < 'xmandel.mot.ad'`"
test 929 -eq "$Wc_c" ||
echo 'xmandel.mot.ad: original size 929, current size' "$Wc_c"
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo You have unpacked the last part
exit 0
--
--
Molecular Simulations, Inc. mail: dcmartin@msi.com
796 N. Pastoria Avenue uucp: uunet!dcmartin
Sunnyvale, California 94086 at&t: 408/522-9236