#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define OUTFILE "buddhabrot"
#define WIDTH 1024
#define HEIGHT 768
#define CENTRE_X -0.451
#define CENTRE_Y 0
#define ZOOM 310 // Try 310
#define SOURCE_COLUMNS (WIDTH * 10)
#define SOURCE_ROWS (HEIGHT * 10)
#define UPDATETICK 100
#define RED_MULTIPLIER 0.09
#define GREEN_MULTIPLIER 0.11
#define BLUE_MULTIPLIER 0.18
#define COLOUR_OFFSET -230
#define RED_ITERATIONS_LOWER 0
#define RED_ITERATIONS_UPPER 1000
#define GREEN_ITERATIONS_LOWER 0
#define GREEN_ITERATIONS_UPPER 1000
#define BLUE_ITERATIONS_LOWER 0
#define BLUE_ITERATIONS_UPPER 1000
#define SOURCE_LEFT_X -2.102613
#define SOURCE_RIGHT_X 1.200613
#define SOURCE_TOP_Y -1.237710
#define SOURCE_BOTTOM_Y 1.239710
#undef RANDOM_SOURCE
#define OPTIMISE
#define reduce(foo) (foo)
////////////////////////////////////////////////////////////////////////////////////
void drawpath(double x, double y, double target_startx, double target_starty, double pixel_width);
double rnd (void);
void drawbmp (char * filename);
////////////////////////////////////////////////////////////////////////////////////
long long redcount[WIDTH][HEIGHT];
long long greencount[WIDTH][HEIGHT];
long long bluecount[WIDTH][HEIGHT];
int iterations;
double red_multiplier = RED_MULTIPLIER;
double green_multiplier = GREEN_MULTIPLIER;
double blue_multiplier = BLUE_MULTIPLIER;
////////////////////////////////////////////////////////////////////////////////////
int main (int argc, char * argv[]) {
int i, j, n;
double x, y;
int source_column, source_row;
double r, s, nextr, nexts;
double x_jump, y_jump;
double target_startx, target_starty;
double target_endx, target_endy;
double pixel_width;
char filename[200];
for (i = 0; i < WIDTH; i++)
{
for (j = 0; j < HEIGHT; j++)
{
redcount[i][j] = 0;
greencount[i][j] = 0;
bluecount[i][j] = 0;
}
}
target_startx = CENTRE_X - ((double) WIDTH / (ZOOM * 2));
target_endx = CENTRE_X + ((double) WIDTH / (ZOOM * 2));
target_starty = CENTRE_Y - ((double) HEIGHT / (ZOOM * 2));
target_endy = CENTRE_Y + ((double) HEIGHT / (ZOOM * 2));
pixel_width = (target_endx - target_startx) / WIDTH;
x_jump = ((double) SOURCE_RIGHT_X - SOURCE_LEFT_X) / SOURCE_COLUMNS;
y_jump = ((double) SOURCE_BOTTOM_Y - SOURCE_TOP_Y) / SOURCE_ROWS;
iterations = RED_ITERATIONS_UPPER;
if (GREEN_ITERATIONS_UPPER > iterations) iterations = GREEN_ITERATIONS_UPPER;
if (BLUE_ITERATIONS_UPPER > iterations) iterations = BLUE_ITERATIONS_UPPER;
// Main bit...
x = SOURCE_LEFT_X;
for (source_column = 0; source_column < SOURCE_COLUMNS; source_column++, x += x_jump)
{
y = SOURCE_TOP_Y;
for (source_row = 0; source_row < SOURCE_ROWS; source_row++, y += y_jump)
{
#ifdef OPTIMISE
if
(
(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)
) continue;
#endif
r = 0; s = 0;
for (n = 0; n <= iterations; n++)
{
nextr = ((r * r) - (s * s)) + x;
nexts = (2 * r * s) + y;
r = nextr;
s = nexts;
if (n == iterations)
{
// drawpath(x, y, target_startx, target_starty, pixel_width);
break;
} else if ((r * r) + (s * s) > 4) {
drawpath(x, y, target_startx, target_starty, pixel_width);
break;
}
}
}
if (source_column % UPDATETICK == 0)
{
printf("Reached source column: %d of %d\n", source_column, SOURCE_COLUMNS);
}
}
sprintf(filename, "%s r %d g %d b %d spp %d.bmp", OUTFILE, RED_ITERATIONS_UPPER, GREEN_ITERATIONS_UPPER, BLUE_ITERATIONS_UPPER, (SOURCE_COLUMNS / WIDTH) * (SOURCE_ROWS / HEIGHT));
drawbmp(filename);
printf("Done.\n");
return 0;
}
void drawpath (double x, double y, double target_startx, double target_starty, double pixel_width)
{
double r, s, nextr, nexts;
int n;
int xpixel, ypixel;
r = 0; s = 0;
for (n = 0; n <= iterations; n++)
{
nextr = ((r * r) - (s * s)) + x;
nexts = (2 * r * s) + y;
r = nextr;
s = nexts;
if ((r * r) + (s * s) > 4) return;
xpixel = (r - target_startx) / pixel_width;
ypixel = (s - target_starty) / pixel_width;
if (xpixel > 0 && xpixel < WIDTH && ypixel > 0 && ypixel < HEIGHT)
{
if (n >= RED_ITERATIONS_LOWER && n <= RED_ITERATIONS_UPPER)
{
redcount[xpixel][ypixel] += 1;
}
if (n >= GREEN_ITERATIONS_LOWER && n <= GREEN_ITERATIONS_UPPER)
{
greencount[xpixel][ypixel] += 1;
}
if (n >= BLUE_ITERATIONS_LOWER && n <= BLUE_ITERATIONS_UPPER)
{
bluecount[xpixel][ypixel] += 1;
}
}
}
return;
}
void drawbmp (char * filename) {
unsigned int headers[13];
FILE * outfile;
int extrabytes;
int paddedsize;
int x; int y; int n;
int red, green, blue;
extrabytes = 4 - ((WIDTH * 3) % 4);
if (extrabytes == 4)
extrabytes = 0;
paddedsize = ((WIDTH * 3) + extrabytes) * HEIGHT;
// Headers...
// Note that the "BM" identifier in bytes 0 and 1 is NOT included in these "headers".
headers[0] = paddedsize + 54;
headers[1] = 0;
headers[2] = 54;
headers[3] = 40;
headers[4] = WIDTH;
headers[5] = HEIGHT;
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");
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);
}
for (y = HEIGHT - 1; y >= 0; y--) // BMP image format is written from bottom to top...
{
for (x = 0; x <= WIDTH - 1; x++)
{
red = reduce(redcount[x][y] + COLOUR_OFFSET) * red_multiplier;
green = reduce(greencount[x][y] + COLOUR_OFFSET) * green_multiplier;
blue = reduce(bluecount[x][y] + COLOUR_OFFSET) * blue_multiplier;
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;
// Also, it's written in (b,g,r) format...
fprintf(outfile, "%c", blue);
fprintf(outfile, "%c", green);
fprintf(outfile, "%c", red);
}
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;
}