Here’s a modified version of the mandelbrot program from the previous post. This time, the generated images are in colour and output in binary PPM format (which is still uncompressed, but a bit more space efficient than the plain text PPM format). Also, I’m generating the images at higher resolution (2560×2560 pixels) so that they can be scaled back down to produce better (“less aliased”) images.
// // mandelbrot.c - Visualise the Mandelbrot Set // written by Ted Burke - last updated 15-12-2012 // // The command line arguments are the real and imaginary parts of // the centre value, the real axis range and the output filename. // // To compile with MinGW: // // gcc mandelbrot.c -o mandelbrot.exe -lm // // To run (this example is centred on point x=-0.7485,y=0.1): // // mandelbrot.exe -0.7485 0.1 0.0001 ms.ppm // #include <stdio.h> #include <stdlib.h> #include <math.h> #define PI 3.14159265 #define W 2560 #define H 2560 // Pixel array int p[H][W]; int main(int argc, char *argv[]) { int x, y; double real_centre, imag_centre, real_range; double cre, cim, cre_min, cre_max, cim_min, cim_max; double zre, zim, zre_next, zim_next; double limit = 100.0; double maxval = 0; // Parse command line arguments if (argc != 5) { printf("Usage: mandelbrot REAL_CENTRE IMAG_CENTRE REAL_RANGE FILENAME\n"); return 0; } real_centre = atof(argv[1]); imag_centre = atof(argv[2]); real_range = atof(argv[3]); cre_min = real_centre - 0.5*real_range; cre_max = real_centre + 0.5*real_range; cim_min = imag_centre - 0.5*H*real_range/W; cim_max = imag_centre + 0.5*H*real_range/W; // Calculate pixel values for (y=0;y<H;++y) { for (x=0;x<W;++x) { // Calculate c value for this pixel cre = cre_min + (cre_max-cre_min)*x/(double)W; cim = cim_min + (cim_max-cim_min)*y/(double)H; // Iterate for current c value p[y][x] = 255; zre = 0; zim = 0; while (fabs(zre) < limit && fabs(zim) < limit && p[y][x] > 0) { zre_next = zre*zre - zim*zim + cre; zim_next = 2*zre*zim + cim; zre = zre_next; zim = zim_next; p[y][x] *= 0.98; } maxval = (p[y][x] > maxval) ? p[y][x] : maxval; } fprintf(stderr, "\rRow %d calculated", y); } fprintf(stderr, "\r "); // Output image to PPM file FILE *f = fopen(argv[4], "w"); int r, g, b; fprintf(f, "P6\n# Image\n%d %d\n255\n", W, H); for (y=0;y<H;++y) { for (x=0;x<W;++x) { b = 255.0 * (0.5 + 0.5*cos(2*PI * p[y][x] / maxval)); r = 255.0 * (0.5 + 0.5*cos(2*PI * p[y][x] / maxval + 2*PI/3.0)); g = 255.0 * (0.5 + 0.5*cos(2*PI * p[y][x] / maxval + 2*PI/1.5)); //fprintf(f, "%03d %03d %03d ", r, g, b); fputc(r, f); fputc(g, f); fputc(b, f); } fprintf(stderr, "\rRow %d written", y); } fprintf(stderr, "\n"); fclose(f); return 0; }
The program generates PPM images 2560x2560px in size. I ran the following commands to produce the image below (ImageMagick’s convert command is used to scale the image and convert to PNG format for uploading to this post):
mandelbrot.exe -0.75 0.0 3.0 zoomout.ppm convert zoomout.ppm -resize 25% zoomout.png
Similarly, the following commands produced the image below:
mandelbrot.exe -0.7485 0.1 0.0001 zoomin.ppm convert zoomin.ppm -resize 25% zoomin.png
Thought you might like this – http://youtu.be/7dcDuVyzb8Y