richb@sunaus.oz (Rich Burridge) (12/27/89)
popi is a program for manipulating digital images. It was posted to comp.sources.misc earlier this month. **Note that popi was released to comp.sources.misc at patchlevel #2** This is the second and final part of official patch #3. Rich Burridge & Stephen Frede. Rich Burridge, DOMAIN: richb@sunaus.oz.au PHONE: +61 2 413 2666 UUCP: {uunet,mcvax,ukc}!munnari!sunaus.oz!richb Stephen Frede, DOMAIN: stephenf@softway.oz.au PHONE: +61 2 698 2322 UUCP: {uunet,mcvax,ukc}!munnari!softway.oz!stephenf ---- Cut Here and unpack ---- #!/bin/sh # this is part 2 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file patch.3 continued # CurArch=2 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file patch.3" sed 's/^X//' << 'SHAR_EOF' >> patch.3 X+ X+ tmp = CurOld->pix; X+ CurOld->pix = img->pix; X+ img->pix = tmp; X+ } X+ } X+ X+ static void X writeimg() X { X! struct SRC *img; X X if (parsefname() == 0) X return; X X! if ((img = parseimg()) == (struct SRC *) 0) X return; X X! putpix(img, text); X } X X static void X*************** X*** 743,749 **** X if ((srcp = parseimg()) == (struct SRC *) 0) X return; X X! if (srcp == &src[CUROLD] || srcp == &src[CURNEW]) X { X SPRINTF(ErrBuf, "Cannot free 'old' or 'new'"); X error(0); X--- 795,801 ---- X if ((srcp = parseimg()) == (struct SRC *) 0) X return; X X! if (srcp == CurOld || srcp == CurNew) X { X SPRINTF(ErrBuf, "Cannot free 'old' or 'new'"); X error(0); X*************** X*** 775,786 **** X if (lat == '\n') X { X pushback(lat); X! img = src[CUROLD].pix; X } X else if (lat == INAME) X! img = src[lexval + 1].pix; X else if (lat == NEW) X! img = src[CURNEW].pix; X else X { X SPRINTF(ErrBuf, "Expected +, - or image name"); X--- 827,838 ---- X if (lat == '\n') X { X pushback(lat); X! img = CurOld->pix; X } X else if (lat == INAME) X! img = Images[lexval].pix; X else if (lat == NEW) X! img = CurNew->pix; X else X { X SPRINTF(ErrBuf, "Expected +, - or image name"); X*************** X*** 857,862 **** X--- 909,934 ---- X } X X static void X+ doparse() X+ { X+ FILE *RunStr; X+ X+ if (parsefname() == 0) X+ return; X+ X+ if ((RunStr = fopen(text, "r")) == NULL) X+ { X+ SPRINTF(ErrBuf, "Can't open run file '%s'", text); X+ error(ERR_SYS); X+ return; X+ } X+ X+ parse(RunStr); X+ X+ FCLOSE(RunStr); X+ } X+ X+ static void X debug() X { X static char *buf = (char *) 0; X*************** X*** 969,974 **** X--- 1041,1048 ---- X { "help", help }, X { "free", freeimg }, X { "logfile", dolog }, X+ { "run", doparse }, X+ { "create", newimg }, X { (char *) 0, (void (*) P((void)) ) 0 } X }; X X X------- atariterm.c ------- X*** /tmp/da1972 Wed Dec 27 12:13:51 1989 X--- atariterm.c Wed Dec 27 10:41:25 1989 X*************** X*** 47,53 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 47,52 ---- X*************** X*** 127,141 **** X { X return(getchar()); X } X- X- X- void X- disp_ungetc(c) /* Put back the last character typed. */ X- char c ; X- { X- UNGETC(c, stdin); X- } X- X X X disp_prompt() /* Display popi prompt and clear input line. */ X--- 126,131 ---- X X------- graphics.c ------- X*** /tmp/da1975 Wed Dec 27 12:13:52 1989 X--- graphics.c Wed Dec 27 10:43:30 1989 X*************** X*** 62,68 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype, pos) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 62,67 ---- X*************** X*** 148,162 **** X tptr = 0 ; X } X return(nextline[tptr++]) ; X- } X- X- X- /*ARGSUSED*/ X- void X- disp_ungetc(c) /* Put back the last character typed. */ X- char c ; X- { X- tptr-- ; X } X X X--- 147,152 ---- X X------- nulldev.c ------- X*** /tmp/da1978 Wed Dec 27 12:13:53 1989 X--- nulldev.c Wed Dec 27 10:48:18 1989 X*************** X*** 30,36 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 30,35 ---- X*************** X*** 71,76 **** X--- 70,76 ---- X } X X X+ int X disp_getchar() /* get next user typed character. */ X { X return(getchar()); X*************** X*** 77,94 **** X } X X X! /*ARGSUSED*/ X! void X! disp_ungetc(c) /* put back the last character typed. */ X! char c; X! { X! UNGETC(c, stdin); X! } X! X! X disp_prompt() /* display popi prompt. */ X { X! char *prompt = "-> "; X X PRINTF(prompt); X return sizeof prompt - 1; X--- 77,86 ---- X } X X X! int X disp_prompt() /* display popi prompt. */ X { X! static char prompt[] = "-> "; X X PRINTF(prompt); X return sizeof prompt - 1; X X------- kerterm.c ------- X*** /tmp/da1981 Wed Dec 27 12:13:53 1989 X--- kerterm.c Wed Dec 27 10:45:58 1989 X*************** X*** 64,70 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 64,69 ---- X*************** X*** 201,215 **** X { X return(getchar()); X } X- X- X- void X- disp_ungetc(c) /* Put back the last character typed. */ X- char c ; X- { X- UNGETC(c, stdin); X- } X- X X X disp_prompt() /* Display popi prompt and clear input line. */ X--- 200,205 ---- X X------- graphics.h ------- X*** /tmp/da1984 Wed Dec 27 12:13:54 1989 X--- graphics.h Wed Dec 27 10:44:04 1989 X*************** X*** 17,22 **** X--- 17,25 ---- X * (see README file) then an attempt will be made to fix them. X */ X X+ #define WRITE (void) write X+ #define IOCTL (void) ioctl X+ X /* External declarations for the variables declared in graphics.c. */ X X extern char geometry[] ; /* X11 geometry information. */ X X------- apollo.c ------- X*** /tmp/da1987 Wed Dec 27 12:13:55 1989 X--- apollo.c Wed Dec 27 10:40:40 1989 X*************** X*** 39,45 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 39,44 ---- X*************** X*** 175,189 **** X disp_getchar() /* get next user typed character. */ X { X return(getchar()); X- } X- X- X- /*ARGSUSED*/ X- void X- disp_ungetc(c) /* put back the last character typed. */ X- char c; X- { X- UNGETC(c, stdin); X } X X X--- 174,179 ---- X X------- amiga.c ------- X*** /tmp/da1990 Wed Dec 27 12:13:55 1989 X--- amiga.c Wed Dec 27 10:39:50 1989 X*************** X*** 40,46 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 40,45 ---- X*************** X*** 138,152 **** X disp_getchar() /* get next user typed character. */ X { X return(getchar()); X- } X- X- X- /*ARGSUSED*/ X- void X- disp_ungetc(c) /* put back the last character typed. */ X- char c; X- { X- UNGETC(c, stdin); X } X X X--- 137,142 ---- X X------- ibmpc.c ------- X*** /tmp/da1993 Wed Dec 27 12:13:56 1989 X--- ibmpc.c Wed Dec 27 10:44:40 1989 X*************** X*** 98,104 **** X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X- * disp_ungetc(c) - put back the last character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype,pos) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X--- 98,103 ---- X*************** X*** 115,120 **** X--- 114,122 ---- X #define PAL_GETPALBLOCK 0x09 /* read all palette registers */ X #define PAL_GETDACBLOCK 0x17 /* read current VGA DAC values */ X #define PAL_SETDACBLOCK 0x12 /* set new VGA DAC values */ X+ #define VID_SETPIXEL 0x0C /* store pixel value */ X+ #define VID_DISPLAY 0x1A /* video display combination */ X+ #define VID_SUBSYSTEM 0x12 /* video subsystem configuration */ X X /* X * Arguments to the vid_vgapalette and vid_setpalette functions X*************** X*** 180,192 **** X { X 0x06, 640, 200, 0xB800, 2, 0x2000, 8, X }, X! #define VID_STD 2 /* Last standard adapter */ X /* From here on, adapters have no bios support. The bios X * number will be stored in the appropriate place in the video X * bios data area (this is useful eg if a mouse is being used, X * so it gets the graphics cursor correct). X */ X! #define VID_HGC 3 X { X 0x06, 720, 348, 0xB000, 4, 0x2000, 8, X }, X--- 182,202 ---- X { X 0x06, 640, 200, 0xB800, 2, 0x2000, 8, X }, X! #define VID_MDA 3 X! { X! 0x06, 640, 200, 0xB800, 2, 0x2000, 8, X! }, X! #define VID_MCGA 4 X! { X! 0x06, 640, 200, 0xB800, 2, 0x2000, 8, X! }, X! #define VID_STD 4 /* Last standard adapter */ X /* From here on, adapters have no bios support. The bios X * number will be stored in the appropriate place in the video X * bios data area (this is useful eg if a mouse is being used, X * so it gets the graphics cursor correct). X */ X! #define VID_HGC 5 X { X 0x06, 720, 348, 0xB000, 4, 0x2000, 8, X }, X*************** X*** 394,400 **** X X regs.h.ah = 0; X regs.h.al = mode; X! int86(0x10, ®s, ®s); X } X X static void X--- 404,410 ---- X X regs.h.ah = 0; X regs.h.al = mode; X! int86(BIOS_VIDFN, ®s, ®s); X } X X static void X*************** X*** 405,417 **** X union REGS regs; X X regs.h.al = value; X! regs.h.ah = 0x0C; X! regs.h.bh = 0; X regs.x.cx = (unsigned) x; X regs.x.dx = (unsigned) y; X! int86(0x10, ®s, ®s); X } X X /* X * Detect installed graphics hardware. X */ X--- 415,433 ---- X union REGS regs; X X regs.h.al = value; X! regs.h.ah = VID_SETPIXEL; X! regs.h.bh = 0; /* video page */ X regs.x.cx = (unsigned) x; X regs.x.dx = (unsigned) y; X! int86(BIOS_VIDFN, ®s, ®s); X } X X+ static unsigned char X+ vid_chkherc() X+ { X+ return VID_MDA; X+ } X+ X /* X * Detect installed graphics hardware. X */ X*************** X*** 418,426 **** X static unsigned char X vid_detect() X { X! /* Yes, well, when I get a chance I'll do this. X! * Wait for the next release. X! */ X return VID_NONE; X } X X--- 434,483 ---- X static unsigned char X vid_detect() X { X! union REGS regs; X! X! regs.h.ah = VID_DISPLAY; X! regs.h.al = 0; /* get video display combination */ X! int86(BIOS_VIDFN, ®s, ®s); X! if (regs.h.al == 0x1a) X! { X! /* VGA or MCGA present - what is the active display? */ X! switch(regs.h.bl) X! { X! case 1: X! /* MDA or hercules */ X! return vid_chkherc(); X! X! case 2: X! return VID_CGA; X! X! case 4: X! case 5: X! return VID_EGA; X! X! case 7: X! case 8: X! return VID_VGA; X! X! case 10: X! case 11: X! case 12: X! return VID_MCGA; X! X! default: X! return VID_NONE; X! } X! } X! X! /* System doesn't have a VGA or MCGA - check for EGA */ X! regs.h.ah = VID_SUBSYSTEM; X! regs.h.bl = 0x10; /* get video configuration information */ X! int86(BIOS_VIDFN, ®s, ®s); X! if (regs.h.bl != 0x10) X! { X! /* EGA BIOS present */ X! return VID_EGA; X! } X return VID_NONE; X } X X*************** X*** 782,799 **** X } X X X- /*ARGSUSED*/ X- void X- disp_ungetc(c) /* put back the last character typed. */ X- int c; X- { X- UNGETC(c, stdin); X- } X- X int X disp_prompt() /* display popi prompt. */ X { X! char *prompt = "-> "; X X PRINTF(prompt); X return sizeof prompt - 1; X--- 839,848 ---- X } X X X int X disp_prompt() /* display popi prompt. */ X { X! static char prompt[] = "-> "; X X PRINTF(prompt); X return sizeof prompt - 1; SHAR_EOF echo "File patch.3 is complete" chmod 0644 patch.3 || echo "restore of patch.3 fails" set `wc -c patch.3`;Sum=$1 if test "$Sum" != "60414" then echo original size 60414, current size $Sum;fi echo "x - extracting hp.c (Text)" sed 's/^X//' << 'SHAR_EOF' > hp.c && X/*LINTLIBRARY*/ X X/* @(#)hp.c 1.1 89/12/27 X * X * Popi device driver for an HP display. X * Written by Eric Haines - 3D/Eye Inc, Ithaca, NY X * X * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs. X * This version is based on the code in his Prentice Hall book, X * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7, X * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. X * X * Permission is given to distribute these extensions, as long as these X * introductory messages are not removed, and no monies are exchanged. X * X * No responsibility is taken for any errors or inaccuracies inherent X * either to the comments or the code of this program, but if reported X * (see README file) then an attempt will be made to fix them. X */ X X#include "popi.h" X#include "graphics.h" X#include <starbase.c.h> X X/* There are ten exportable routines used by the popi program. X * X * These are: X * X * disp_init(argc, argv) - called from main at the start. X * disp_finish() - called from main prior to exit. X * disp_imgstart() - called prior to drawing an image. X * disp_imgend() - called after drawing an image. X * disp_putline(line, y) - to draw an image scanline. X * disp_getchar() - to get the next character typed. X * disp_prompt() - display popi prompt and clear input buffer. X * disp_error(errtype) - display error message. X * disp_percentdone(n) - display percentage value of conversion. X */ X Xextern char *getenv(); X X/* Default device names. To change, set the environment variables X * OUTDEV and OUTDRIVER appropriately. See code in "devopen". X */ Xchar default_indev[] = "/dev/hil2" ; Xchar default_indriver[] = "hp-hil" ; Xchar default_outdev[] = "/dev/hp98721" ; Xchar default_outdriver[] = "hp98721" ; X Xint fd ; X Xvoid Xdisp_init(argc,argv) /* called from main at the start. */ Xint argc; Xchar *argv[]; X{ X fd = devopen(OUTDEV,INIT) ; X if ( fd == -1 ) { X printf("error opening output device\n" ) ; X exit(1) ; X } X vdc_extent( fd, 0.0, 0.0, 0.0, 1.25, 1.0, 1.0 ) ; X shade_mode( fd, CMAP_MONOTONIC | INIT ) ; X make_picture_current( fd ) ; X} X X Xvoid Xdisp_finish() /* called from main prior to exit. */ X{ X gclose( fd ) ; X} X X Xvoid Xdisp_imgstart() /* called prior to drawing an image. */ X{ X} X X Xvoid Xdisp_imgend() /* called after drawing an image. */ X{ X} X X Xvoid Xdisp_putline(line, y) /* called to draw image scanline y. */ Xpixel_t *line; Xint y; X{ X dcblock_write( fd, 0,y,Xsize,1,line,0) ; X} X X Xdisp_getchar() /* get next user typed character. */ X{ X return(getchar()); X} X X Xdisp_prompt() /* display popi prompt. */ X{ X PRINTF("-> "); X return 3; X} X X Xvoid Xdisp_error(errtype, pos) /* display error message. */ Xint errtype, X pos; X{ X extern int errno; X extern char *sys_errlist[]; X X if (errtype & ERR_PARSE) X { X int i; X X for (i=1; i < pos; ++i) X PUTC('-', stderr); X PUTC('^', stderr); X PUTC('\n', stderr); X } X X fprintf(stderr, "%s\n", ErrBuf); X /* we assume errno hasn't been reset by the preceding output */ X if (errtype & ERR_SYS) X fprintf(stderr, "\t(%s)\n", sys_errlist[errno]); X} X Xvoid Xdisp_percentdone(percent) Xint percent; X{ X static int lastpercent = 100; X X if (!Verbose) X return; X if (percent == 100) X { X printf("\r \n"); X return; X } X if (percent != lastpercent && percent % 5 == 0) X { X printf("\r%2d%% ", percent); X fflush(stdout); X lastpercent = percent; X } X} X Xint devopen(dev_kind,init_mode) Xint dev_kind,init_mode; X{ Xchar *dev, *driver; Xint fildes ; X X if ( dev_kind == OUTDEV ) { X dev = getenv("OUTDEV"); X if (!dev) dev = default_outdev ; X driver = getenv("OUTDRIVER"); X if (!driver) driver = default_outdriver ; X } else { X dev = getenv("INDEV"); X if (!dev) dev = default_indev ; X driver = getenv("INDRIVER"); X if (!driver) driver = default_indriver ; X } X X fildes = gopen(dev,dev_kind,driver,init_mode); X X return(fildes) ; X} SHAR_EOF chmod 0444 hp.c || echo "restore of hp.c fails" set `wc -c hp.c`;Sum=$1 if test "$Sum" != "4087" then echo original size 4087, current size $Sum;fi echo "x - extracting popi.man (Text)" sed 's/^X//' << 'SHAR_EOF' > popi.man && X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X XNAME X popi - perform interactive digital image transformations X XSYNOPSIS X popi [option] ... [file] ... X XDESCRIPTION X Popi is a program which allows arbitrary transformations to X be interactively applied to digital images. It is based on X the program described in "Beyond Photography - The Digital X Darkroom" by Gerald J. Holzmann. The meanings of the avail- X able command line options are as follows: X X -V Print program version identification message and exit. X X -xWidth X Set the image width (number of pixels per scanline) to X Width . X X -yHeight X Set the image height (number of scanlines) to Height . X X -v+ Set the verbose flag on. Be chatty about a number of X things. X X -v- Turn the verbose flag off. Be silent about everything X except error messages. X X -a+ Turn auto-display on. After each image transformation, X the image will be displayed. Equivalent to the X #display + command. X X -a- Turn auto-display off. Equivalent to the #display - X command. Images can still be displayed explicitly with X the #display image command. X X -p[ncpus] X On a Sequent multiprocessor, use the specified number X of cpus to perform the transform. If this option is X given without a number, the maximum number available is X used. This option has no effect on uniprocessor com- X puters. X X -l[logfile] X Enables logging of all input, error messages, and some X responses. Logging is done on the named file, or the X file "popi.log" if no name is given. The #logfile com- X mand may also be used to turn logging on and off. An X image transform is described by a transform statement. X The statement basically takes the form X X dest = expression X X X X X Sun Release 4.0 Last change: 20 December 1989 1 X X X X X X X POPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X where dest indicates the new image and expression X describes a transformation. This statement is executed X over the range of image coordinates. For a 512 x 512 X image, it will be executed 262144 times. An image is X normally referenced in a statement by its name and an X index. A cartesian index is specified by using the x X and y coordinates in square brackets after the image X name. Thus dmr[0,0] is the top left pixel in the image X named dmr. Polar coordinates may be specified by giving X a radius and angle (in degrees) in curly brackets. X Thus dmr{0,0} refers to the centre pixel in the image. X The symbols x and y may appear in the transform state- X ment. These take on values corresponding to a dif- X ferent pixel each time the transform is executed. X Internally the algorithm is as follows X X for y varying from 0 to Y X for x varying from 0 to X X execute transform statement X X where Y is the maximum y coordinate and X is the max- X imum x coordinate. The image size can be set on the X command line as described later. The value of a pixel X varies from 0 to 255 in the current implementation. X Any value outside this range is treated as modulo 256 X when being stored in an image (ie. it wraps around). X Low numeric values represent dark colours, while large X values represent light colours. A simple transform X statement to set an image to completely black would be X X new[x,y] = 0 ; set image to black X X The name new is one of the two default images always X maintained internally. The other is old. The images X referred to by these names are swapped after each X operation, so a succession of transforms may modify the X "old" image to produce a "new" image. Thus the state- X ment X X new[x,y] = old[x,y] / 2 ; darken image X X will reduce all the pixel intensity values by a half, X darkening the existing image. The semicolon (`;') X character introduces a comment. Anything from this to X the end of the line is ignored. All the standard X arithmetic, relational and boolean operators from the C X language are available, with precedence generally as X per the C language. Some additional operators, prede- X fined variables and math functions are also available. X Here is a listing of the available symbols and their X meanings. X X name Refers to an image name. If not followed by index X brackets, the index [x,y] is assumed. The currently X available names are those shown by the #list display, X X X XSun Release 4.0 Last change: 20 December 1989 2 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X and also old and new. X X $n Where n is a digit, this is an alternative method of X referring to an image. In fact this may be the only X method if the image name contains punctuation charac- X ters. The #list command shows the correspondence X between image names and this form of reference. X X X The maximum x coordinate value. This is one less than X the number of pixels per scanline (image width), which X may be set with the -x command line option. X X Y The maximum y coordinate value. This is one less than X the number of scanlines (the height of the image), X which may be set with the -y command line option. X X x The current cartesian x coordinate. Varies from 0 X (left of image) to X (right of image). X X y The current cartesian y coordinate. Varies from 0 (top X of image) to Y (bottom of image). X X r The radius component of the polar coordinate which X corresponds to the current cartesian (x,y) coordinate. X This is equivalent to sqrt(x*x + y*y) with a transla- X tion of the origin. X X a The angle component of the polar coordinate which X corresponds to the current cartesian (x,y) coordinate. X This is equivalent to (and a shorthand for) atan(y/x). X X Note that the first time in a popi session you use an X expression with either r or a in it, you may notice an X extra delay before the image transformation begins. X This is due to precalculation of an array of polar X coordinates that happens the first time you use one. X X R The maximum radius value of a polar coordinate. X X A The maximum angle value of a polar coordinate (this is X just 360). X X Z The maximum intensity value of a pixel (corresponding X to white). Currently, this is always 255. X X ** The exponentiation (raise to the power) operator. The X expression x ** 2 means x squared (x * x). X X * The multiplication operator. This has a higher pre- X cedence than division to avoid underflow in expressions X with multiplication and division, since normally X expressions are evaluated as integers. X X X XSun Release 4.0 Last change: 20 December 1989 3 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X / Integer division. If the divisor is 0, the result is X set to Z. X X % Modulo. If the divisor (right hand operand) is 0, the X result is set to 0. X X + Addition. X X - Subtraction. This may be a unary or a binary operator. X X << Left shift. The left operand is shifted left the X number of bits specified by the right operand. X X >> Right shift. The left operand is shifted right the X number of bits specified by the right operand. X X > Greater than. As with all the relational operators, if X the specified relation between the operands is true, X the result is 1, otherwise the result is 0. X X < Less than. X X >= Greater than or equal to. X X <= Less than or equal to. X X == Test for equality. X X != Not equal to. X X & Bitwise (arithmetic) AND operator. X X ^ Bitwise exclusive OR (XOR) operator. X X | Bitwise (arithmetic) OR operator. X X && Logical AND operator. The result is 1 if both of the X operands are true (non-zero); otherwise the result is X 0. Unlike the && operator of the C language, this X operator is currently not conditional. Both operands X are always evaluated. X X || Logical OR operator. The result is 1 if both either X (or both) of the operands are true (non-zero); other- X wise the result is 0. Unlike the || operator of the C X language, this operator is currently not conditional. X Both operands are always evaluated. X X sin(expr) X This gives the value of the trigonometric sine of the X expression, multiplied by Z. This is required because X all operations are performed with integers. X X X XSun Release 4.0 Last change: 20 December 1989 4 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X cos(expr) X This gives the value of the trigonometric cosine of the X expression, multiplied by Z. This is required because X all operations are performed with integers. X X atan(y-expr,x-expr) X This returns the trigonometric arctangent (inverse X tangent) of y-expr/x-expr in degrees (ie the value X returned will be between 0 and 360). X X log(expr) X Returns the natural logarithm of the expression. X X sqrt(expr) X Returns the square root of the expression. X X rand() X Returns a positive random number. This will usually be X used with the modulo or bitwise AND operator to res- X trict the range of the result. For example, X X new[x,y] = old[x,y] + rand() % 20 - 10 X X will adjust the brightness levels of each pixel in the X old image by a random amount (up to 10 levels brighter X or darker). As well as allowing transformation state- X ments, a number of special commands, each starting with X a # character, are allowed. These are described here. X X #read "filename" [image-name] X Read a raw data file into the named image. If no image X name is specified, the name is derived from the base X name component of the filename. If the name already X exists, that image is overwritten in memory, otherwise X a new image is created. If the filename does not X exist, but the same name with a ".Z" suffix does exist, X it is assumed that the file is compressed and the X "zcat" program is used to read the compressed image. X Note that when the image name defaults to the file X name, only the basename (portion after the last '/' X character, if any) is used to name the image. If this X resulting name starts with a digit, or contains any X characters other than alphabetic, digits and the under- X score, you will not be able to reference the image by X name, but will have to use the alternative "$n" syntax. X X #write "filename" [image-name] X Write a raw data file from the named image. The image X name is optional, and if not specified, image "old" is X used. If the first character of the filename is `|', X the rest of the filename is interpreted as a command to X be run, with the raw image data being fed to it as X standard input. X X X XSun Release 4.0 Last change: 20 December 1989 5 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X #list X All the named images (other than "old" and "new" are X listed). X X #genps "filename" [image-name] X Generate postscript to produce the image. The image X name is optional, and if not specified, image "old" is X used. The image will be scaled to fit whatever paper X size is being used. As with the #write command, if the X first character of the filename is a `|' symbol, the X rest of the string will be treated as a command to be X executed, with the postscript being piped to its stan- X dard input. This is convenient for printing images on X a PostScript printer. X X #undo X The old and new images are swapped. This has the X effect of restoring the image that existed before the X last transformation. X X #genepson "filename" [image-name] X Generate data for an Epson (or compatible) printer to X produce the image. The image name is optional, and if X not specified, image "old" is used. Under MSDOS, the X device name can be used directly (eg "PRN"). X X The existing code is for a 24-pin printer such as the X LQ-500. To generate data for an 8-pin printer requires X a couple of minor modifications to function genepson() X in file special.c. X X #undo X The old and new images are swapped. This has the X effect of restoring the image that existed before the X last transformation. X X #display image-name X The named image will be displayed. This is the fastest X way to display an image, and works regardless of the X state of auto-display. X X #display + X Turn auto-display on (equivalent to the command-line X option -a+ ). X X #display - X Turn auto-display off (equivalent to the command-line X option -a- ). X X #truncate + X All assignments to an image with values outside the X range 0 to Z will be truncated to the appropriate X X X XSun Release 4.0 Last change: 20 December 1989 6 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X boundary, instead of wrapping as described in the book. X An example of using this feature would be for a X simplistic lightening of an image by adding a constant X value. Normally, very white areas would wrap around X and become black, but enabling truncation prevents X this. X X #truncate - X All assignments to an image will be done modulo (Z+1). X This is the default. X X #truncate X Report whether truncation is currently in effect or X not. X X #verbose + X Turn on verbose mode. Equivalent to the -v+command X Certain warning messages will be printed. This turns X on the "percent done" feature of some drivers (on oth- X ers it is always active). X X #verbose - X Turn off verbose mode. Equivalent to the -v-command X X #verbose X Report the state of the verbose flag. X X #logfile + X Enable logging on the current log file (default X "popi.log"). If logging is already enabled, the file X is closed and re-opened with a new timestamp appended. X X #logfile - X Disable logging" X X #logfile "filename" X Enable logging on the specified file. X X Whenever a log file is opened, it is always opened in X append mode, so existing data is never truncated. Upon X opening a log file, a timestamp is written. All user X input is logged, along with error messages and some X program responses. X X #create imagename X Memory is allocated for a new image. This image is then X swapped with the current image (the result of the last X transformation). X X #run "filename" X Commands are read and executed from the given filename. X X X X XSun Release 4.0 Last change: 20 December 1989 7 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X #free imagename X The memory associated with the named image is freed. X Any further access to this image becomes impossible. X This command may be useful in situations where memory X is very limited, such as a PC. The remaining special X commands are used to obtain special built-in transfor- X mations, as described in Chapter 6 of "Beyond Photogra- X phy". In each of these cases, the image name is X optional, and defaults to "old". In each case (except X for #melt), the result is stored in "new", and then X "old" and "new" are swapped as usual. In the case of X #melt, the transformation is done in place and no swap X occurs. X X #oil image-name X X #shear image-name X X #slice image-name X X #tile image-name X X #melt image-name X X #matte image-name gamma X In this case, gamma is an optional floating point X number (defaults to 7.5). See the book for details. X XDIFFERENCES X There are a number of differences between the Pico inter- X preter, for which the examples in the book are written, and X the Popi interpreter as implemented here. Integer evalua- X tion stack. The current version of the interpreter has an X integer evaluation stack. For this reason, the sin() and X cos() functions, have their results multiplied by Z automat- X ically in order to be significant. A future version of the X interpreter will provide the option for a floating point X stack, and a syntax which will handle both cases. Polar X coordinates. In the book, both cartesian and polar coordi- X nates are specified with square brackets. The decision of X whether to interpret the indices as polar or cartesian is X based on context; if the symbols r and a are used in the X index expressions, the coordinates are interpreted as polar, X otherwise they are interpreted as rectangular. Thus, in X order to use a radius or angle in a cartesian coordinate X expression, it must be cast, as is done on page 48 of the X book. By providing a separate syntax for polar and carte- X sian coordinate references, the problem never occurs. X XEXAMPLES X These examples are mainly taken from the book, with syntax X modifications where required. The images in the book are X X X XSun Release 4.0 Last change: 20 December 1989 8 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X usually 1000 x 1000 pixels. To produce the same results on X a smaller image, you may need to multiply any occurences of X x, y and r by an appropriate scaling factor. The first X example image generation in the book is X X new[x,y] = x + y ; page 17 (3.1) X X which produces a number of diagonal stripes, each fading X from black to white. On a 512 x 512 image, to get the same X number of stripes, use the transform X X new[x,y] = x*2 + y*2 X X A series of ripples can be produced with X X new[x,y] = (x * y) % (Z + 1) ; page 18 (3.2) X X or more simply, because all brightness values are inherently X modulo (Z + 1) unless truncation is turned on X X new[x,y] = x * y X X A single smooth transition can be accomplished with X X new[x,y] = (Z * x * y) / ((X-1) * (Y-1)) ; page 18 (3.3) X X The transformation X X new[x,y] = x % y X X is the same as new[x,y] = x when x < 0 (ie in the lower left X triangle of the image, with a different effect in the upper X right half. The trig functions allow transforms such as X X new[x,y] = y + sin(x) / 2 ; page 19 (3.5) X X which produce a series of sine waves (remember that the X range of sin(x) is +-Z. An image reminiscent of a radar X sweep can be produced by X X new[x,y] = atan(y - Y/2, x - X/2) * Z / 360 ; page 19 (3.6) X X The atan() function has a range of 0 .. 360, so the *Z/360 X rescales to 0 .. Z. This transform is overall providing an X intensity relative to the angle of a point in polar coordi- X nates. The transform language provides the current angle as X the variable a, so this statement can be rewritten as X X new[x,y] = a * Z / 360 X X Polar coordinates can be used to produce an image which X varies from black in the centre to white on the outside X X new[x,y] = r * Z / R ; page 21 (3.11) X X or a spiraling effect X X new[x,y] = (((a + r) % 16) - 8) * Z / 16 + Z/2 ; page 21 (3.12) X X The conditional operator can be used to provide a filled X black circle X X new[x,y] = r > R/2 ? 0 : Z X X X X X Sun Release 4.0 Last change: 20 December 1989 9 X X X X X X X POPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X or black and white patterns such as X X new[x,y] = ((x % (5 + y/25)) > 5) ? 0 : Z ; page 20 (3.9) X new[x,y] = (Z * abs(x % sin(y)) > 10) ? 0 : Z ; page 20 (3.10) X X We can also modify existing images using these transforms. X The previous image can always be referred to as old, or an X explicitly named image can be used. We can read an image X (eg of Dennis Ritchie) using X X #read "dmr" ; read the image in the file "dmr" and name it dmr. X X and then use it in a transform, such as X X new[x,y] = Z - dmr[x,y] ; page 22 (3.13) X X This produces a negative, which can be written to a file X with X X #write "dmr neg" X X or converted to PostScript and printed with X X #genps "| lp -dalw" X X Since the new image built during a transformation becomes X the old image of the following transform, the negative image X can be re-reversed to produce the original with X X new[x,y] = Z - old[x,y] ; reverse the process X X In the following examples, we will use old in most of the X transforms, rather than a particular image name. In prac- X tice, you would probably use a specifically named image X instead. Provide a circular frame for an image X X new[x,y] = r > R/2 ? 0 : old[x,y] X X A solarisation process, that fades in from left to right X X new[x,y] = (old[x,y] > (Z*x) / (2 * X)) ? old[x,y] : Z-old[x,y] ; page 22 (3.16) X X Generate a relief map X X new[x,y] = old[x,y] + (Z/2 - old[x+2,y+2]) ; page 24 (3.19) X X Shrink an image X X new[x,y] = old[x*2,y*2] ; page 25 (3.24) X X An interesting caricature is produced by X X new[x,y] = old{sqrt(r * R),a} ; page 34 X X Note the use of polar coordinates. The reverse transform X gives a fisheye lens effect: X X new[x,y] = old{(r*r)/R, a} ; page 60 X X The following transform illustrates how an expression can be X used for the indices of the destination matrix. X X new[x, y-old[x,y]/4] = old[x,y] ; page 40 X X An image can be swirled about the centre with X X X XSun Release 4.0 Last change: 20 December 1989 10 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X new[x,y] = old{r, a + r/3} X X The following transform uses polar coordinate values in a X cartesian reference, resulting in something that looks like X what you'd see in a cylindrical mirror X X new[x,y] = old[a * X/A, r * Y/R] ; page 48 X X The image generated by X X new[x,y] = old{ (r/16)*16, (a/16)*16 } ; page 72 X X is very interesting, in that it is completely unrecognisable X when viewed up close, but from a distance of a few metres it X will resolve into the original. X X new[x,y] = old{r, a + old{r,a}/8} ; page 68 X X This image is a swirl, but with the skew dependant on the X brightness of the current point. X X new[x,y] = x < X/2 ? old[x,y] : old[X-x,y] X new[x,y] = x > X/2 ? old[x,y] : old[X-x,y] X X These transformations do a horizontal mirror reversal about X the centre of the image. Because faces are usually close X to, but not exactly, centered, this transform of a face can X be interesting. X X new[x,y] = old[x+(x%32)-16, y] ; page 58 X new[x,y] = old[x+((a+r/10)%32)-16, y] X X These transforms applied to a face produce what looks like X someone peering through a bathroom window. X XDRIVERS X nulldev X The null device driver is mainly for people with no X graphics display device for which a driver exists. X Using this device, data for a PostScript or Epson X printer can still be generated. X X atariterm X The atari driver is for use with "TERM", a multiplexing X terminal program for the Atari ST, written by Peter X Collinson of the University of Kent at Canterbury. It X is not a driver for running native on an atari. X X kermit X This is a driver for MS-Kermit 2.32 on an IBM PC, which X is capable of emulating a Tektronix 4010. This provides X three levels of contrast (nothing, normal and bold). X X MGR This driver is for the Bell Core MGR window system. It X is visually identical to the SunView version, but is X currently hardwired to monochrome. X X NeWS This is the driver that will work with NeWS v1.1 and X X X XSun Release 4.0 Last change: 20 December 1989 11 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X OpenWindows v1.0. It is also visually identical to the X SunView version. X X pcturbo X This is a driver for running popi native on a PC with X Borland's Turbo C compiler. It uses the graphics X library supplied with Turbo C, which auto-detects most X types of graphics display. No attempt at using a X colourmap is done - a single display dot is used for X each image pixel, with simple dithering. Only directly X accesible memory is used, which drastically restricts X the size of images that can be handled. X X SunView X This driver is the initial version to work with the X SunView graphics package available on Sun Workstations. X There is currently minimal functionality. The output X is in 256 greyscales on colour machines, and an 8x8 X dither on monochrome screens. X X X11 A graphics implementation for use with MIT's X11 window X system. This driver is visually identical to the Sun- X View version. X X XView X A conversion of the SunView graphics driver to use the X XView X11 toolkit. This driver is visually identical to X the SunView version. X XSEE ALSO X ipscript(1L), imavg(1L). X XAUTHOR X Gerald J. Holzmann, AT&T Bell Laboratories, Murray Hill, New X Jersey. X X Modifications and additional functionality, Atari, PC, X PostScript, Epson and null drivers by Stephen Frede, Softway X Pty Ltd, Australia. X Popi maintainance, SunView, X11, NeWS, MGR and XView graph- X ics drivers by Rich Burridge, Sun Microsystems, Australia. X Kermit graphics driver by Frank Crawford, Q.H. Tours. X Amiga graphics driver by Peter Chubb, Softway Pty Ltd, Aus- X tralia. X Apollo driver by Tim Lambert, University of New South Wales. X HP driver by Eric Haines, 3D/Eye Inc, Ithaca, NY. X XBUGS X Functions which require popen() (ie auto reading of X compressed files and writing to pipes) don't work in the X sequent multiprocessor version. X X X X XSun Release 4.0 Last change: 20 December 1989 12 X X X X X X XPOPI(1L) MISC. REFERENCE MANUAL PAGES POPI(1L) X X X X Probably more - please notify richb@sunaus.oz.au of any X found. X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XSun Release 4.0 Last change: 20 December 1989 13 X X X SHAR_EOF chmod 0444 popi.man || echo "restore of popi.man fails" set `wc -c popi.man`;Sum=$1 if test "$Sum" != "28800" then echo original size 28800, current size $Sum;fi rm -f s2_seq_.tmp echo "You have unpacked the last part" exit 0