User:Nippoo/Mandelbrot.c


 * 1) include 
 * 2) include 
 * 3) include 


 * 1) define OUTFILE "mandelbrot.bmp"

////////////////////////////////////////////////////////////////////////////////////


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


 * 1) define CENTRE_X 0.282
 * 2) define CENTRE_Y 0.01
 * 3) define ZOOM 150000


 * 1) define ITERATIONS 7000

// Plotting functions and parameters...


 * 1) define bailoutr(n) bailoutsqrt(n, 12)  // Try instead: bailoutlinear(n, 1.5)
 * 2) define bailoutg(n) bailoutsqrt(n, 3) // Try instead: bailoutlinear(n, 0.35)
 * 3) define bailoutb(n) 0

// Subsamples, where we look "inside" each pixel for values and average them. // Useful for despeckling the image, may "seem" to blur it slightly though... // These values must be at least one.


 * 1) define SUBSAMPLES_X 2
 * 2) define SUBSAMPLES_Y 2

// Colours for the set itself...


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

////////////////////////////////////////////////////////////////////////////////////

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

void setrgb (struct imagemap * bitmapstruct, int x, int y, int red, int green, int blue); void cls (struct imagemap * bitmapstruct, int red, int green, int blue); void drawbmp (struct imagemap * bitmapstruct, char * filename); int bailoutlinear(int i, float multiplier); int bailoutsqrt(int i, float multiplier); int bailoutlog(int i, float multiplier); int bailoutsquared(int i, float multiplier); void init_imagemap(struct imagemap * bitmapstruct, int width, int height); int getr(struct imagemap * bitmapstruct, int x, int y); int getg(struct imagemap * bitmapstruct, int x, int y); int getb(struct imagemap * bitmapstruct, int x, int y);

////////////////////////////////////////////////////////////////////////////////////

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; int red, green, blue; int tmpred, tmpgreen, tmpblue; int subxnumber, subynumber; double subx, suby;

struct imagemap bitmap;

init_imagemap(&bitmap, WIDTH, HEIGHT); cls(&bitmap, IN_SET_R, IN_SET_G, IN_SET_B);

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 Mandelbrot...\n From: %.10f, %.10f\n  To: %.10f, %.10f\n\n", startx, starty, endx, endy); printf(" 0%%      20%%       40%%       60%%       80%%       100%%\n ");

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

/*

- The actual screen pixel being plotted is in variables xtoplot and ytoplot.

- Coordinates we're Mandelbrotting are in variables x and y. - We are interested in coordinates from (startx, starty) to (endx, endy).

- What distance a pixel covers has been calculated above and is dx_over_width.

- We do subsampling - for each pixel, "subpixels" are examined, and the colour is averaged. - subxnumber and subynumber keep track of which subsample we are on, ie the first (which is 0), second (1) etc. - subx and suby store the actual coordinates of the subpixel, for the Mandelbrot iteration. These will be x or y plus (the distance a subpixel covers, multiplied by subxnumber or subynumber).



x = startx; for (xtoplot = 0; xtoplot < WIDTH; xtoplot++) {  if (xtoplot % (WIDTH / 50) == 0) {     printf("."); fflush(stdout); }  y = starty; for (ytoplot = 0; ytoplot < HEIGHT; ytoplot++) {     // To optimise a bit, we skip past bits in the main cardioid + it's major bulb // which are definitely in the set...
 * 1) ifndef NO_OPTIM

while (        (x >  -1.2 && x <=  -1.1 && y >  -0.1 && y < 0.1)      || (x >  -1.1 && x <=  -0.9 && y >  -0.2 && y < 0.2)      || (x >  -0.9 && x <=  -0.8 && y >  -0.1 && y < 0.1)      || (x > -0.69 && x <= -0.61 && y >  -0.2 && y < 0.2)      || (x > -0.61 && x <=  -0.5 && y > -0.37 && y < 0.37)      || (x >  -0.5 && x <= -0.39 && y > -0.48 && y < 0.48)      || (x > -0.39 && x <=  0.14 && y > -0.55 && y < 0.55)      || (x >  0.14 && x <   0.29 && y > -0.42 && y < -0.07)      || (x >  0.14 && x <   0.29 && y >  0.07 && y < 0.42)      ) {        // Uncomment to see optimised areas... // setrgb(&bitmap, xtoplot, ytoplot, 255, 255, 255, GFX_REPLACE); ytoplot++; y += dx_over_width; if (ytoplot >= HEIGHT - 1) {           break; }     }      red = 0; green = 0; blue = 0; for (subxnumber = 0; subxnumber < SUBSAMPLES_X; subxnumber++) {        subx = x + (subxnumber * dx_over_width / SUBSAMPLES_X); for (subynumber = 0; subynumber < SUBSAMPLES_Y; subynumber++) {           suby = y + (subynumber * dx_over_width / SUBSAMPLES_Y);
 * 1) endif

r = subx; s = suby;      // r = 0; s = 0;  also works (just adds an iteration) for (n = 0; n <= ITERATIONS; n++) {              nextr = ((r * r) - (s * s)) + subx; nexts = (2 * r * s) + suby; r = nextr; s = nexts; if (n == ITERATIONS) {                 red += IN_SET_R; green += IN_SET_G; blue += IN_SET_B; break; } else if ((r * r) + (s * s) > 4) { tmpred = bailoutr(n); tmpgreen = bailoutg(n); tmpblue = bailoutb(n); // These lines kinda alter the effect of the subsampling... arguably nicer without... // if (tmpred > 255) tmpred = 255; // if (tmpgreen > 255) tmpgreen = 255; // if (tmpblue > 255) tmpblue = 255; red += tmpred; green += tmpgreen; blue += tmpblue; break; }           }         }      }      red = red / (SUBSAMPLES_X * SUBSAMPLES_Y); green = green / (SUBSAMPLES_X * SUBSAMPLES_Y); blue = blue / (SUBSAMPLES_X * SUBSAMPLES_Y); setrgb(&bitmap, xtoplot, ytoplot, red, green, blue); y += dx_over_width; }  x += dx_over_width; }

drawbmp(&bitmap, OUTFILE); printf("\n\n Saved to %s. Time elapsed: %d seconds.\n", OUTFILE, clock / CLOCKS_PER_SEC);

return 0; }

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

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; }

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 each // horizontal 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...  // Note that the "BM" identifier in bytes 0 and 1 is NOT included in these "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

// Would have biPlanes and biBitCount in position 6, but they're shorts. // It's easier to write them out separately (see below) than pretend // they're a single int, especially with endian issues...

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--)    // BMP image format is written from bottom to top... {     for (x = 0; x <= bitmapstruct->width - 1; x++) {        // Also, it's written in (b,g,r) format... fprintf(outfile, "%c", getb(bitmapstruct, x, y)); fprintf(outfile, "%c", getg(bitmapstruct, x, y)); fprintf(outfile, "%c", getr(bitmapstruct, x, y)); }     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; }

////////////////////////////////////////////////////////////////////////////////////

// Some functions here that can be used as the bailout functions (see top)...

int bailoutlinear(int i, float multiplier) {  return i * multiplier; }

int bailoutsqrt(int i, float multiplier) {  if (i < 0) return 0; return sqrt(i) * multiplier; }

int bailoutlog(int i, float multiplier) {  if (i < 0) return 0; return log(i) * multiplier; }

int bailoutsquared(int i, float multiplier) {  if (i < 0) return 0; return i * i * multiplier; }

////////////////////////////////////////////////////////////////////////////////////

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 * sizeof(char)); if (bitmapstruct->pixels == NULL) {     printf("   Memory allocation failed. Quitting.\n"); exit(1); }  return; }

int getr(struct imagemap * bitmapstruct, int x, int y) { if (x < 0 || x >= bitmapstruct->width || y < 0 || y >= bitmapstruct->height) {     return 0; }  return (int) bitmapstruct->pixels[(x * 3) + (y * bitmapstruct->width * 3)]; }

int getg(struct imagemap * bitmapstruct, int x, int y) { if (x < 0 || x >= bitmapstruct->width || y < 0 || y >= bitmapstruct->height) {     return 0; }  return (int) bitmapstruct->pixels[(x * 3) + 1 + (y * bitmapstruct->width * 3)]; }

int getb(struct imagemap * bitmapstruct, int x, int y) { if (x < 0 || x >= bitmapstruct->width || y < 0 || y >= bitmapstruct->height) {     return 0; }  return (int) bitmapstruct->pixels[(x * 3) + 2 + (y * bitmapstruct->width * 3)]; }