From: Joshua Wise Date: Fri, 25 Jul 2008 04:39:51 +0000 (-0400) Subject: initial import X-Git-Url: http://git.joshuawise.com/mandelbrot-c.git/commitdiff_plain/refs/heads/master?ds=sidebyside initial import --- 28dc4dc20085b83cb1b177f7e0e8a49217fb55c1 diff --git a/mandelbrot.c b/mandelbrot.c new file mode 100644 index 0000000..1765630 --- /dev/null +++ b/mandelbrot.c @@ -0,0 +1,488 @@ +#include "SDL.h" +#include +#include +#include +#include +#include + +/* Algorithmic variables */ +int maxiters = 256; +#define BAILOUT 2.0 +int xres = 600; +int yres = 600; +double xmin = -2, ymin = -2, xmax = 2, ymax = 2; + +/* Display variables */ +SDL_Surface* screen; +SDL_Color palette[256],origpalette[256]; +int ppm = 0; +int sdl = 1; +int cycling = 0; + +int iterate(double x, double y) +{ + int i; + double cplxr, cplxi; + cplxr = y; + cplxi = x; + i = 0; + while ((i < maxiters) && (hypot(cplxr, cplxi) < BAILOUT)) + { + double a=cplxr, b=cplxi, c=cplxr, d=cplxi; + i++; + cplxr = a*c-b*d+y; + cplxi = a*d+b*c+x; + } + return i; +} + +void set_palette() +{ + if (sdl) + SDL_SetColors(screen, palette, 0, 256); +} + +void cycle_colors() +{ + SDL_Color x; + int i; + x = palette[0]; + for (i=0; i<255; i++) + palette[i] = palette[i+1]; + palette[255] = x; + set_palette(); +} + +Uint32 cycle_colors_cbk(Uint32 interval) +{ + cycle_colors(); + return interval; +} + +void init_palette() +{ + int i; + for (i=0; i<256; i++) + { + palette[i].r = sin(((double)i)/256.0*2.0*M_PI*5.0f)*256.0; + palette[i].g = sin(((double)(i+64))/256.0*2.0*M_PI*4.0f)*256.0; + palette[i].b = sin(((double)(i+128))/256.0*2.0*M_PI*3.0f)*256.0; + origpalette[i] = palette[i]; + } +} + +int videoflags = SDL_SWSURFACE | SDL_RESIZABLE; + +void start_sdl() +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) + { + printf("SDL init failed: %s\n", SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + screen = SDL_SetVideoMode(xres, yres, 8, videoflags); + if (!screen) + { + printf("SDL video init failed: %s\n", SDL_GetError()); + exit(1); + } + + SDL_WM_SetCaption("Mandelbrot Set", "Mandelbrot"); +} + +double pxltofltx(int x) +{ + return ((double)x)*((double)(xmax-xmin))/((double)xres)+xmin; +} +double pxltoflty(int y) +{ + return ((double)y)*((double)(ymax-ymin))/((double)yres)+ymin; +} + +void render() +{ + int x,y; + Uint8* buffer; + if (ppm) + printf("P6\n%d %d\n255\n", xres, yres); + if (sdl) + { + cycling = 0; + SDL_WM_SetCaption("Mandelbrot Set [working]", "Mandelbrot"); + SDL_SetTimer(0, NULL); + SDL_LockSurface(screen); + buffer = (Uint8*)screen->pixels; + } + for (y=0;ypitch; + if (!(y%10)) + { + if (sdl) + { + for (x=0;x.\n" + , me + ); + exit(2); +} + +struct option longopts[] = { + {"x", required_argument, NULL, 'x'}, + {"width", required_argument, NULL, 'x'}, + {"y", required_argument, NULL, 'y'}, + {"height", required_argument, NULL, 'y'}, + {"maxiters", required_argument, NULL, 'm'}, + {"sdl", no_argument, NULL, 's'}, + {"ppm", no_argument, NULL, 'p'}, + {"no-sdl", no_argument, NULL, 'S'}, + {"no-ppm", no_argument, NULL, 'P'}, + {"help", no_argument, NULL, 'h'}, + {"location", required_argument, NULL, 'l'}, + {"palette", required_argument, NULL, 't'}, + {"quit-immediately", no_argument, NULL, 'q'}, + {0,0,0,0} +}; + +int main(int argc, char** argv) +{ + SDL_Event event; + int startx, starty; + int buttondown = 0; + int dragged = 0; + int arg; + int custompalette = 0; + int quitimmediately = 0; + double yctr, ysz; + + while ((arg = getopt_long(argc, argv, "x:y:m:l:t:sSpPq", longopts, NULL)) != -1) + { + switch(arg) + { + case 'x': + xres = atoi(optarg); + if (!xres) + { + printf("%s: option `%c' requires an integer argument\n", argv[0], arg); + printf("Try `%s --help' for more information.\n", argv[0]); + exit(2); + } + break; + case 'y': + yres = atoi(optarg); + if (!yres) + { + printf("%s: option `%c' requires an integer argument\n", argv[0], arg); + printf("Try `%s --help' for more information.\n", argv[0]); + exit(2); + } + break; + case 'm': + maxiters = atoi(optarg); + if (!maxiters) + { + printf("%s: option `%c' requires an integer argument\n", argv[0], arg); + printf("Try `%s --help' for more information.\n", argv[0]); + exit(2); + } + break; + case 's': + sdl = 1; + break; + case 'p': + ppm = 1; + quitimmediately = 1; + break; + case 'S': + sdl = 0; + break; + case 'P': + ppm = 0; + break; + case 'h': + usage(argv[0]); + break; + case 'l': + { + float f1,f2,f3,f4; + if (sscanf(optarg, "%f,%f,%f,%f", &f1, &f2, &f3, &f4) != 4) + { + printf("%s: incorrect syntax for option `%c'\n", argv[0], arg); + printf("Try %s --help' for more information.\n", argv[0]); + exit(2); + } + xmin = f1; xmax = f2; ymin = f3; ymax = f4; + } + break; + case 't': + custompalette = load_palette(optarg); + break; + case 'q': + quitimmediately = 1; + break; + case '?': + case ':': + printf("Try `%s --help' for more information.\n", argv[0]); + exit(2); + break; + default: + printf("Oh God I am not good with computers how did this get here?\n"); + exit(127); + } + } + + if (sdl) + start_sdl(); + yctr = ymin + (ymax - ymin) / 2.0; + // get y in proportion + ysz = (xmax-xmin)*((double)yres)/((double)xres); + ymax = yctr+ysz/2; ymin = yctr-ysz/2; + + if (!custompalette) + init_palette(); + set_palette(); + render(); + if (quitimmediately) + exit(0); + while ( SDL_WaitEvent(&event) ) { + switch (event.type) { + case SDL_KEYDOWN: + if (event.key.keysym.sym == SDLK_c) + { + if (!cycling) + { + SDL_WM_SetCaption("Mandelbrot Set [color cycling]", "Mandelbrot"); + SDL_SetTimer(50, cycle_colors_cbk); + } else { + SDL_WM_SetCaption("Mandelbrot Set", "Mandelbrot"); + SDL_SetTimer(0, NULL); + } + cycling = !cycling; + } else if (event.key.keysym.sym == SDLK_r) { + int i; + for (i=0;i<256;i++) + { + palette[i].r = origpalette[i].r; + palette[i].g = origpalette[i].g; + palette[i].b = origpalette[i].b; + } + set_palette(); + } else if (event.key.keysym.sym == SDLK_ESCAPE || + event.key.keysym.sym == SDLK_q) { + exit(0); + } else if (event.key.keysym.sym == SDLK_p) { + ppm = 1; + render(); + ppm = 0; + } else if (event.key.keysym.sym == SDLK_RETURN) { + render(); + } else if (event.key.keysym.sym == SDLK_i) { + printf("mandelbrot by Joshua Wise\n"); + printf("2005-06-19, Little Cayman\n"); + printf("\n"); + printf("Current settings:\n"); + printf(" xmin: %f, xmax: %f\n", xmin, xmax); + printf(" ymin: %f, ymax: %f\n", ymin, ymax); + printf(" maxiters: %d, bailout: %f\n", maxiters, BAILOUT); + printf(" xres: %d, yres: %d\n", xres, yres); + printf("Recreate with:\n"); + printf(" %s -x%d -y%d -l%f,%f,%f,%f -m%d\n", argv[0], xres,yres,xmin,xmax,ymin,ymax,maxiters); + } + break; + case SDL_MOUSEBUTTONDOWN: + if (event.button.button == 1) + buttondown = 1; + startx = event.button.x; + starty = event.button.y; + break; + case SDL_MOUSEMOTION: + if (buttondown) + dragged = 1; + break; + case SDL_MOUSEBUTTONUP: + if (event.button.button == 1) + buttondown = 0; + if (!dragged) + { + if (event.button.button == 1 || event.button.button == 3) + { + double xsz = xmax-xmin, ysz = ymax-ymin; + double x,y; + double scalar; + if (event.button.button == 1) + scalar = 1.0/2.0; + else + scalar = 2.0/1.0; + xsz *= scalar; + ysz *= scalar; + x = pxltofltx(event.button.x); + y = pxltoflty(event.button.y); + xmax = x + xsz / 2; + xmin = x - xsz / 2; + ymax = y + ysz / 2; + ymin = y - ysz / 2; + render(); + } else if (event.button.button == 2) { + xmax = ymax = 2; + xmin = ymin = -2; + render(); + } + dragged = 0; + break; + } else { + double newmaxx, newminx, newmaxy, newminy; + if (event.button.x > startx) + { + newmaxx = pxltofltx(event.button.x); + newminx = pxltofltx(startx); + } else { + newminx = pxltofltx(event.button.x); + newmaxx = pxltofltx(startx); + } + if (event.button.y > starty) + { + newmaxy = pxltoflty(event.button.y); + newminy = pxltoflty(starty); + } else { + newminy = pxltoflty(event.button.y); + newmaxy = pxltoflty(starty); + } + yctr = newminy + (newmaxy - newminy) / 2.0; + // get y in proportion + ysz = (newmaxx-newminx)*((double)yres)/((double)xres); + ymax = yctr+ysz/2; ymin = yctr-ysz/2; + xmax = newmaxx; xmin = newminx; + render(); + dragged = 0; + break; + } + case SDL_VIDEORESIZE: + { + screen = SDL_SetVideoMode(event.resize.w, event.resize.h, + screen->format->BitsPerPixel, + videoflags); + if (!screen) + { + fprintf(stderr, "Couldn't resize screen\n"); + exit(1); + } + SDL_SetColors(screen, palette, 0, 256); + xres = event.resize.w; + yres = event.resize.h; + yctr = ymin + (ymax - ymin) / 2.0; + // get y in proportion + ysz = (xmax-xmin)*((double)yres)/((double)xres); + ymax = yctr+ysz/2; ymin = yctr-ysz/2; + render(); + break; + } + case SDL_QUIT: + return; + } + } + return 1; +}