Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site ecsvax.UUCP Path: utzoo!watmath!clyde!bonnie!akgua!mcnc!ecsvax!bet From: bet@ecsvax.UUCP (Bennett E. Todd III) Newsgroups: net.sources Subject: Mandelbrot set programs Message-ID: <416@ecsvax.UUCP> Date: Sat, 14-Sep-85 15:42:58 EDT Article-I.D.: ecsvax.416 Posted: Sat Sep 14 15:42:58 1985 Date-Received: Sun, 15-Sep-85 23:57:44 EDT Reply-To: duccpc!bet@ecsvax.UUCP (Bennett E. Todd III) Followup-To: net.sources.bugs Distribution: net Organization: Duke University Computation Center Lines: 727 #!/bin/sh # Cut above the preceeding line, or cut here if you must. # This is a shar archive. Extract with sh, not csh. # The rest of this file will extract: # mndlbrot.doc compute.c ibmcg4.c colorprn.c sed 's/^X//' > mndlbrot.doc << '/*EOF' XThis is a set of programs written in C for computing and displaying the XMandelbrot set. The program "compute" generates a data file containing a Xdescriptive header, followed by one byte per pixel, containing the count Xof how many iterations were required to diverge. This work was based on Xthe cover article of the August 1985 Scientific American, the Computer XRecreations column. Please consult that article for a description of the Xwhys and wherefores of this algorithm. The programs "ibmcg4" and X"colorprn" display the resulting files on the IBM Color Graphics Adaptor Xin 4 colors, and the IBM Personal Computer Color Printer in 8 colors, Xrespectively. They should be reasonably easily modified for other Xdevices, and aside from two short assembler subroutines "setup_scr()" Xand "putpoint()" in ibmcg4, should be reasonably portable. These were Xwritten under DeSmet C for the IBM-PC. The header of the data file is Xterminated by a byte value 26 decimal, ^Z, which is the DOS EOF marker. XThis shouldn't interfere with the program in other environments, and Xenables you to read the header on a PC by simply typing "type file.pic", Xas the type command stops at EOF. Feel free to rip out the \032 in the Xfprintf and fscanf statements if you don't like this cuteness. X XThe arguments used to describe a picture are four: center and scale, Xwhich are complex constants, and hpix and vpix, integers defining the Xnumber of pixels horizontally and vertically respectively. Center is the Xcomplex coordinates of the center of the picture. The picture runs from Xreal(center)-real(scale) to real(center)+real(scale) on the real axis, Xand similarly in the complex direction. I am open to suggestions for Xmore meaningful input parameters to control these critters; this just Xseemed simplest at the time (i.e. before I realized what is involved in Xgenerating pictures with "true" proportions). Perhaps it should compute Xthe imaginary scale factor, and you should also input what dimensions Xthe hpix*vpix window will display as, or maybe the compute program Xshould have the aspect ratios of various output devices wired in, or Xsomething. Think about it and let me know what you come up with:-). X XI put some effort into making the programs completely controllable from Xthe command line, using named parameters that can come in any order and Xare prompted for if missing and like that. This is the first time I have Xdone this, and the result has a lot of duplicated code. I would welcome Xany cleaning up anyone could do on that part, which constitutes the vast Xmajority of compute.c. X XThese programs were inspired by the program John White wrote, and he Xhelp to debug them and speed them up. They are designed with a different Xgoal from John's; his is exceedingly fast, many times faster than mine. XI placed the highest priorities on portability and clarity, with speed Xtaking a slow third. My programs aren't intended as competitors in any Xsense to that which John wrote; they represent a different set of design Xtradeoffs. X XThe display program ibmcg4 has two different color assignment schemes Xselectable via compile time #ifdef code; I made an adaptive color Xassignment that seemed to be reasonable, then John White gave me his, Xwhich resolves much better detail in four colors. Colorprn uses adaptive Xcolor assignment alone, though I used a little of John's color banding Xapproach. These are probably the best place to try to improve the Xappearance of the resulting pictures. X XFinal note: these programs are formatted with tabs every 4 columns, not 8. X XPlease send me any bug fixes and enhancements you might make to these; I Xam continuing to work on them and will keep you informed of any Ximprovements I make, if I get any indication of interest. Enjoy. X XBennett Todd XDuke Computation Center XDurham NC 27701 X+1 919 684 3695 XUUCP: ...{decvax,ihnp4,akgua}!mcnc!ecsvax!duccpc!bet XBITNET: dbtodd@tucc /*EOF ls -l mndlbrot.doc sed 's/^X//' > compute.c << '/*EOF' X#include X/* X * compute [name] [center=x+yi] [scale=x+yi] [hpix=n] [vpix=n] [like=name] X * Build file name.pix, containing a header with the center, scale X * and horizontal/vertical pixel info, followed by hpix*vpix bytes X * containing the number of iterations required for the point to go X * to infinity (up to 255). Any parameters not specified on the command X * line are prompted for, after a one-line summery of the command line X * syntax. X * like=name allows you to set defaults to those of another picture, then X * override them. X */ X X#define MAXNAMELEN 64 /* MS-DOS filename length limit */ X X#ifndef FALSE X#define FALSE 0 X#endif X X#ifndef TRUE X#define TRUE 1 X#endif X X#define ISPREFIX(s1, s2) !strncmp((s1), (s2), strlen(s1)) X#define ISSUFFIX(s1, s2) !strcmp((s1), (s2)+strlen(s2)-strlen(s1)) X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int got_name = FALSE, X got_center = FALSE, X got_scale = FALSE, X got_hpix = FALSE, X got_vpix = FALSE; X char name[MAXNAMELEN], /* picture name */ X iobuff[128]; /* kbd input buffer */ X double center_r, /* real part of center */ X center_i, /* imaginary " */ X scale_r, /* real part of scale */ X scale_i; /* imaginary " */ X int hpix, /* # pixels horizontal */ X vpix; /* # " vertical */ X double top_left_r, X top_left_i, X hstep, X vstep; X int i,j; X FILE *fp, *fopen(); X X /* check for a "like" parameter; process it if found; */ X for (i=1; i ibmcg4.c << '/*EOF' X#include X/* X * ibmcg4 [name] X * Display file name.pic created by compute on an IBM Color Graphics X * Adaptor in 4 colors. Prompts for name if not given. X */ X X#define MAXNAMELEN 64 /* max filename length for MS-DOS */ X X#define John_White_Colors X X#ifndef FALSE X#define FALSE 0 X#endif X X#ifndef TRUE X#define TRUE 1 X#endif X X#ifndef EOF X#define EOF (-1) X#endif X X#define ISSUFFIX(s1, s2) !strcmp((s1), (s2)+strlen(s2)-strlen(s1)) X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char name[MAXNAMELEN]; X FILE *fp, *fopen(); X int i, j, n; X double center_r, X center_i, X scale_r, X scale_i; X int hpix, vpix; X char colormax[4]; X long npix, count[256], temp_l; X X if (argc == 2) X if (ISSUFFIX(".pic", argv[1])) X strncpy(name, argv[1], MAXNAMELEN); X else { X strncpy(name, argv[1], MAXNAMELEN-4); X strcat(name, ".pic"); X } X else { X printf("syntax: ibmcg4 [name]\n"); X printf("Name: "); X gets(name); X } X if (!ISSUFFIX(".pic", name)) X strcat(name, ".pic"); X while ((fp = fopen(name, "r")) == NULL) { X fprintf(stderr, "ibmcg4: cannot open %s\n", name); X printf("Name: "); X gets(name); X if (!ISSUFFIX(".pic", name)) X strcat(name, ".pic"); X } X X if (fscanf(fp, "Centered at %lf+%lfi, scale %lf+%lfi, %dx%d\n\032", X ¢er_r, ¢er_i, &scale_r, &scale_i, &hpix, &vpix) != 6) { X fprintf(stderr, "ibmcg4: cannot parse header of %s\n", name); X exit(1); X } X X npix = hpix*(long)vpix; X X#ifndef John_White_Colors X for (i=0; i<256; i++) X count[i] = 0; X X for (temp_l = 0; temp_l < npix; temp_l++) { X if ((n=fgetc(fp)) == EOF) { X fprintf(stderr, "ibmcg4: too few pixels!\n"); X exit(1); X } X count[n]++; X } X X if (lseek(fp, -npix, 1) <= 0) { X fprintf(stderr, "ibmcg4: lseek funkiness!\n"); X exit(1); X } X X temp_l = 0; X for (i=0; temp_l < npix/3; i++) X temp_l += count[i]; X colormax[0] = i; X X while (temp_l < 2*npix/3) X temp_l += count[i++]; X colormax[1] = i; X X colormax[2] = 254; X colormax[3] = 255; X#endif X X setup_scr(); X for (i=0; i127) ? 3 : /* White */ X (n&1) + 1); /* Huh? */ X#endif X } X getchar(); X} X Xsetup_scr() X{ X#asm X xor ax,ax ; set mode X mov al,4 ; 320x200 color X int 10h ; video_io (BIOS) X X mov ah,11 ; set pallette X mov bh,0 ; background X mov bl,0 ; black X int 10h ; video_io (BIOS) X X mov ah,11 ; set pallette X mov bh,1 ; pallette X mov bl,1 ; Cyan(1), Magenta(2), White(3) X int 10h ; video_io (BIOS) X# X} X Xputpoint(x, y, c) Xint x, /* [BP+4] */ X y, /* [BP+6] */ X c; /* [BP+8] */ X{ X#asm X mov ah,12 ; write dot X mov al,[bp+8] X mov dx,[bp+4] X mov cx,[bp+6] X int 10h ; video_io X# X} /*EOF ls -l ibmcg4.c sed 's/^X//' > colorprn.c << '/*EOF' X#include X/* X * colorprn [name] [outfile] X * Display file name.pic created by compute on an X * IBM Personal Computer Color Printer, in 16 colors. X * Prompts for name if not given. Output goes to PRN: by default. X */ X X#define MAXNAMELEN 64 /* max filename length for MS-DOS */ X X#ifndef FALSE X#define FALSE 0 X#endif X X#ifndef TRUE X#define TRUE 1 X#endif X X#ifndef EOF X#define EOF (-1) X#endif X X#define ISSUFFIX(s1, s2) !strcmp((s1), (s2)+strlen(s2)-strlen(s1)) X X#define WHITE 0 X#define YELLOW 1 X#define MAGENTA 2 X#define CYAN 3 X#define BLACK 4 X#define ORANGE 5 X#define GREEN 6 X#define VIOLET 7 X#define BROWN 8 X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char name[MAXNAMELEN]; X FILE *fp, *fo, *fopen(); X int i, j, k, n, colormask; X double center_r, X center_i, X scale_r, X scale_i; X int hpix, vpix; X char color[256]; X long npix, count[256], temp_l; X char *obuff[9], *malloc(); X X /* get and open the file to print */ X if (argc > 1) X if (ISSUFFIX(".pic", argv[1])) X strncpy(name, argv[1], MAXNAMELEN); X else { X strncpy(name, argv[1], MAXNAMELEN-4); X strcat(name, ".pic"); X } X else { X printf("syntax: colorprn [name]\n"); X printf("Name: "); X gets(name); X } X if (!ISSUFFIX(".pic", name)) X strcat(name, ".pic"); X while ((fp = fopen(name, "r")) == NULL) { X fprintf(stderr, "colorprn: cannot open %s\n", name); X printf("Name: "); X gets(name); X if (!ISSUFFIX(".pic", name)) X strcat(name, ".pic"); X } X X /* snarf its parameters from its header */ X if (fscanf(fp, "Centered at %lf+%lfi, scale %lf+%lfi, %dx%d\n\032", X ¢er_r, ¢er_i, &scale_r, &scale_i, &hpix, &vpix) != 6) { X fprintf(stderr, "colorprn: cannot parse header of %s\n", name); X exit(1); X } X X /* set up the output file */ X if (argc > 2) { X if ((fo = fopen(argv[2], "w")) == NULL) { X fprintf(stderr, "colorprn: cannot open %s\n", argv[2]); X exit(1); X } X } else X if ((fo = fopen("PRN:", "w")) == NULL) { X fprintf(stderr, "colorprn: cannot open PRN:\n"); X exit(1); X } X X /* number of pixels in the entire image */ X npix = hpix*(long)vpix; X X /* zero out frequency count buckets */ X for (i=0; i<256; i++) X count[i] = 0; X X /* collect a count of the frequency of occurrence of each byte value */ X for (temp_l = 0; temp_l < npix; temp_l++) { X if ((n=fgetc(fp)) == EOF) { X fprintf(stderr, "colorprn: too few pixels!\n"); X exit(1); X } X count[n]++; X } X X /* rewind to the beginning of the image */ X if (lseek(fp, -npix, 1) <= 0) { X fprintf(stderr, "colorprn: lseek funkiness!\n"); X exit(1); X } X X /* adaptively assign colors according to areas (from frequency count) */ X temp_l = 0; X color[255] = BLACK; X for (i=254; temp_l < ((npix-count[255])/50); i--) { X color[i] = WHITE; X temp_l += count[i]; X } X while (temp_l < ((npix-count[255])/20)) { X color[i] = YELLOW; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/10)) { X color[i] = ORANGE; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/8)) { X color[i] = MAGENTA; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/6)) { X color[i] = GREEN; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/4)) { X color[i] = CYAN; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/3)) { X color[i] = VIOLET; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])/2)) { X color[i] = CYAN; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])*2/3)) { X color[i] = VIOLET; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])*3/4)) { X color[i] = CYAN; X temp_l += count[i--]; X } X while (temp_l < ((npix-count[255])*5/6)) { X color[i] = VIOLET; X temp_l += count[i--]; X } X while (i >= 0) X color[i--] = BROWN; X X /* allocate color mapping and print line generation buffers */ X for (i=0; i<9; i++) X if ((obuff[i] = malloc(hpix)) == NULL) { X fprintf(stderr, "colorprn: too little memory for obuff\n"); X exit(1); X } X X /* set printer aspect ratio to 1:1, with unidirectional printing */ X fprintf(fo, "\033n\001\033U"); X X /* for each printer row (8 pix vertically) */ X for (i=0; i> j; X for (k=0; k>8); X if (fwrite(obuff[YELLOW], 1, hpix, fo) != hpix) { X fprintf(stderr, "colorprn: write error to %s %s\n", X (argc > 2) ? argv[2] : X "PRN:", X (argc > 2) ? ", disk full?" : X ", printer fault?"); X exit(1); X } X fprintf(fo, "%c", 141); X break; X } X for (k=0; k>8); X if (fwrite(obuff[MAGENTA], 1, hpix, fo) != hpix) { X fprintf(stderr, "colorprn: write error to %s %s\n", X (argc > 2) ? argv[2] : X "PRN:", X (argc > 2) ? ", disk full?" : X ", printer fault?"); X exit(1); X } X fprintf(fo, "%c", 141); X break; X } X for (k=0; k>8); X if (fwrite(obuff[CYAN], 1, hpix, fo) != hpix) { X fprintf(stderr, "colorprn: write error to %s %s\n", X (argc > 2) ? argv[2] : X "PRN:", X (argc > 2) ? ", disk full?" : X ", printer fault?"); X exit(1); X } X fprintf(fo, "%c", 141); X break; X } X for (k=0; k>8); X if (fwrite(obuff[BLACK], 1, hpix, fo) != hpix) { X fprintf(stderr, "colorprn: write error to %s %s\n", X (argc > 2) ? argv[2] : X "PRN:", X (argc > 2) ? ", disk full?" : X ", printer fault?"); X exit(1); X } X fprintf(fo, "%c", 141); X break; X } X X /* and advance to a new line -- 14/144 inch for graphics */ X fprintf(fo, "\033J%c", 14); X } X fclose(fo); X} /*EOF ls -l colorprn.c exit -- "Hypocrisy is the vaseline of social intercourse." (Who said that?) Bennett Todd -- Duke Computation Center, Durham, NC 27706-7756; (919) 684-3695 UUCP: ...{decvax,seismo,philabs,ihnp4,akgua}!mcnc!ecsvax!duccpc!bet Brought to you by Super Global Mega Corp .com