More Mandelbrot

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

Zoomed out Mandelbrot Set image

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

Zoomed in Mandelbrot Set image

Advertisements
This entry was posted in Uncategorized and tagged , , , , , , , , . Bookmark the permalink.

One Response to More Mandelbrot

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s