User:Evercat/Mandelbrot.c

// Mandelbrot.c // Written by User:Evercat // // This draws the Mandelbrot set and spits out a .bmp file. // Should be quite portable (endian issues have been taken // care of, for example) // // Released under the GNU Free Documentation License // or the GNU Public License, whichever you prefer: // 9 February, 2004.


 * 1) include 


 * 1) define OUTFILE "mandelbrot.bmp"


 * 1) define WIDTH 1024
 * 2) define HEIGHT 768


 * 1) define CENTRE_X -0.75
 * 2) define CENTRE_Y 0
 * 3) define ZOOM 300


 * 1) define ITERATIONS 256 // Higher is more detailed, but slower...

// Plotting functions and parameters...


 * 1) define bailoutr(n) n * 10
 * 2) define bailoutg(n) n * 20
 * 3) define bailoutb(n) 0

// Colours for the set itself...


 * 1) define IN_SET_R 0
 * 2) define IN_SET_G 0
 * 3) define IN_SET_B 0

// Declare imagemap structure...

struct imagemap { int width; int height; unsigned char * pixels;    // this will point to a malloc of unsigned chars. };

// Prototypes...

void init_imagemap(struct imagemap * bitmapstruct, int width, int height); void setrgb(struct imagemap * bitmapstruct, int x, int y, int red, int green, int blue); void drawbmp(struct imagemap * bitmapstruct, char * filename);

/////////////////////////////////// MAIN PROGRAM ///////////////////////////////////

int main (void) {

double x; double r; double nextr; double y; double s; double nexts; int n; int xtoplot; int ytoplot; double startx; double endx; double starty; double endy; double dx; double dy; double dx_over_width;

struct imagemap bitmap;

init_imagemap(&bitmap, WIDTH, HEIGHT);

startx = CENTRE_X - ((double) WIDTH / (ZOOM * 2)); endx = CENTRE_X + ((double) WIDTH / (ZOOM * 2));

starty = CENTRE_Y - ((double) HEIGHT / (ZOOM * 2)); endy = CENTRE_Y + ((double) HEIGHT / (ZOOM * 2));

printf("\n  Plotting from (%f, %f) to (%f, %f)\n", startx, starty, endx, endy);

dx = endx - startx; dy = endy - starty; dx_over_width = dx / WIDTH;

for ((x = startx) && (xtoplot = 0); xtoplot < WIDTH; (x += dx_over_width) && xtoplot++) {  for ((y = starty) && (ytoplot = 0); ytoplot < HEIGHT; (y += dx_over_width) && ytoplot++) {     r = x; s = y;                   // r = 0; s = 0;  also works (just adds an iteration) for (n = 0; n <= ITERATIONS; n++) {        nextr = ((r * r) - (s * s)) + x;         nexts = (2 * r * s) + y;         r = nextr; s = nexts; if (n == ITERATIONS) {           setrgb(&bitmap, xtoplot, ytoplot, IN_SET_R, IN_SET_G, IN_SET_B); } else if ((r * r) + (s * s) > 4) { setrgb(&bitmap, xtoplot, ytoplot, bailoutr(n), bailoutg(n), bailoutb(n)); break; }     }   } }

drawbmp(&bitmap, OUTFILE); printf("\n  Saved to %s. Done.\n", OUTFILE);

return 0; }

//////////////////////////////// GRAPHICS ROUTINES /////////////////////////////////

// Function for initialising a bitmap (which already exists)...

void init_imagemap(struct imagemap * bitmapstruct, int width, int height) {  bitmapstruct->width = width; bitmapstruct->height = height; bitmapstruct->pixels = (unsigned char *) malloc(bitmapstruct->width * bitmapstruct->height * 3); if (bitmapstruct->pixels == NULL) {     printf("Memory allocation failed. Quitting.\n"); exit(1); }  return; }

// Set a pixel...

void setrgb(struct imagemap * bitmapstruct, int x, int y, int red, int green, int blue) {  if (x < 0 || x >= bitmapstruct->width || y < 0 || y >= bitmapstruct->height) return;

if (red > 255) red = 255; if (red < 0) red = 0; if (green > 255) green = 255; if (green < 0) green = 0; if (blue > 255) blue = 255; if (blue < 0) blue = 0; bitmapstruct->pixels[(x * 3) + 0 + (y * bitmapstruct->width * 3)] = red; bitmapstruct->pixels[(x * 3) + 1 + (y * bitmapstruct->width * 3)] = green; bitmapstruct->pixels[(x * 3) + 2 + (y * bitmapstruct->width * 3)] = blue; return; }

// Draw a .bmp file...

void drawbmp (struct imagemap * bitmapstruct, char * filename) {

unsigned int headers[13]; FILE * outfile; int extrabytes; int paddedsize; int x; int y; int n;

extrabytes = 4 - ((bitmapstruct->width * 3) % 4); // How many bytes of padding to add to                                                    // eachhorizontal line - the size of                                                     // which must be a multiple of 4 bytes. if (extrabytes == 4) extrabytes = 0;

paddedsize = ((bitmapstruct->width * 3) + extrabytes) * bitmapstruct->height;

// Headers... headers[0] = paddedsize + 54;      // bfSize (whole file size) headers[1] = 0;                    // bfReserved (both) headers[2] = 54;                   // bfOffbits headers[3] = 40;                   // biSize headers[4] = bitmapstruct->width;  // biWidth headers[5] = bitmapstruct->height; // biHeight // 6 will be written directly... headers[7] = 0;                    // biCompression headers[8] = paddedsize;           // biSizeImage headers[9] = 0;                    // biXPelsPerMeter headers[10] = 0;                   // biYPelsPerMeter headers[11] = 0;                   // biClrUsed headers[12] = 0;                   // biClrImportant

outfile = fopen (filename, "wb");

// Headers begin...  // When printing ints and shorts, we write out 1 character at a time to avoid endian issues.

fprintf (outfile, "BM");

for (n = 0; n <= 5; n++) {     fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int) 0xFF000000) >> 24); }

// These next 4 characters are for the biPlanes and biBitCount fields.

fprintf(outfile, "%c", 1); fprintf(outfile, "%c", 0); fprintf(outfile, "%c", 24); fprintf(outfile, "%c", 0);

for (n = 7; n <= 12; n++) {     fprintf(outfile, "%c", headers[n] & 0x000000FF); fprintf(outfile, "%c", (headers[n] & 0x0000FF00) >> 8); fprintf(outfile, "%c", (headers[n] & 0x00FF0000) >> 16); fprintf(outfile, "%c", (headers[n] & (unsigned int) 0xFF000000) >> 24); }

// Headers done, now write the data...

for (y = bitmapstruct->height - 1; y >= 0; y--) // BMPs are written bottom to top. {     for (x = 0; x <= bitmapstruct->width - 1; x++) {        // Also, it's written in (b,g,r) format... fprintf(outfile, "%c", bitmapstruct->pixels[(x * 3) + 2 + (y * bitmapstruct->width * 3)]); fprintf(outfile, "%c", bitmapstruct->pixels[(x * 3) + 1 + (y * bitmapstruct->width * 3)]); fprintf(outfile, "%c", bitmapstruct->pixels[(x * 3) + 0 + (y * bitmapstruct->width * 3)]); }     if (extrabytes)      // See above - BMP lines must be of lengths divisible by 4. {        for (n = 1; n <= extrabytes; n++) {           fprintf(outfile, "%c", 0); }     }   }

fclose (outfile); return; }