Commit 0df3feb5 authored by Andreas Kempe's avatar Andreas Kempe

Moved the mandelbrot drawer to a class.

parent 08813f3e
#include <mpi.h>
#include <iostream>
#include <Magick++.h>
#include <complex>
#include <cmath>
#include <sstream>
#include <iomanip>
#define IMG_WIDTH 10640
#define IMG_HEIGHT 8000
#define ITERATIONS 2000
#define RE_MAX 1
#define RE_MIN -2
#define IM_MAX 1.4
#define IM_MIN -1.3
using namespace std;
using namespace Magick;
struct MandelResult
{
float end_iterations;
bool belongs;
MandelResult(unsigned long end_iterations, bool belongs) :
end_iterations(end_iterations), belongs(belongs) {}
};
complex<double> GetPixelCoordinate(int x, int y)
{
double re_size = abs(RE_MAX) + abs(RE_MIN);
double im_size = abs(IM_MAX) + abs(IM_MIN);
double re_pp = re_size / IMG_WIDTH;
double im_pp = im_size / IMG_HEIGHT;
return complex<double>(re_pp * x + RE_MIN, im_pp * y + IM_MIN);
}
MandelResult IsMandelbrotPoint(unsigned long x, unsigned long y, unsigned int iterations)
{
complex<double> point = GetPixelCoordinate(x, y);
complex<double> series_value(0, 0);
for (unsigned long i = 0; i < iterations; ++i)
{
if (real(series_value) * real(series_value) + imag(series_value) * imag(series_value) >= 4)
return MandelResult(i + 1 - log(log(abs(pow(series_value, 2) + point))) / log(2), false);
series_value= pow(series_value, 2) + point;
}
return MandelResult(iterations, true);
}
int main(int argc, char** argv)
{
int id;
int procs;
float *calculated_values;
float *receive_buffer = nullptr;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &procs);
MPI_Comm_rank(MPI_COMM_WORLD, &id);
int effective_height = IMG_HEIGHT;
// Calculate this threads working area.
effective_height /= procs;
calculated_values = new float[IMG_WIDTH * effective_height];
for (unsigned long y = effective_height * id; y < effective_height * (id + 1); ++y)
{
for (unsigned long x = 0; x < IMG_WIDTH; ++x)
{
MandelResult result = IsMandelbrotPoint(x, y, ITERATIONS);
calculated_values[(y - effective_height * id) * IMG_WIDTH + x] = result.end_iterations;
}
}
if (id == 0)
receive_buffer = new float[IMG_WIDTH * IMG_HEIGHT];
cout << "Process: " << id << ", Gathering!" << endl;
MPI_Gather(calculated_values, IMG_WIDTH * effective_height, MPI_FLOAT, receive_buffer,
IMG_WIDTH * effective_height, MPI_FLOAT, 0, MPI_COMM_WORLD);
cout << "Process: " << id << ", done gathering!" << endl;
if (id == 0)
{
Image my_image(Geometry(IMG_WIDTH, IMG_HEIGHT), "white");
my_image.modifyImage();
Pixels pixel_cache(my_image);
PixelPacket *pixels = pixel_cache.get(0, 0, IMG_WIDTH, IMG_HEIGHT);
float max = 0;
for (unsigned long i = 0; i < IMG_WIDTH * IMG_HEIGHT; ++i)
{
if (receive_buffer[i] > max && receive_buffer[i] != ITERATIONS)
max = receive_buffer[i];
}
cout << max << endl;
cout << "Assembling image!" << endl;
for (unsigned long y = 0; y < IMG_HEIGHT; ++y)
{
cout << "Progress: " << setprecision(3) <<
static_cast<float>(y * 100) / IMG_HEIGHT << " % \r" << flush;
for (unsigned long x = 0; x < IMG_WIDTH; ++x)
{
int iter_res = receive_buffer[y * IMG_WIDTH + x];
if (iter_res == ITERATIONS)
pixels[y * IMG_WIDTH + x] = Color(MaxRGB * 0.55, MaxRGB * 0.35, MaxRGB * 0.6);
else
pixels[y * IMG_WIDTH + x] = Color(MaxRGB * cosf(exp(iter_res)), 0, MaxRGB * sinf(exp(iter_res)));
}
}
pixel_cache.sync();
cout << "Progress: 100 % " << endl;
stringstream ss;
ss << "output.png";
cout << "Saving image!" << endl;
my_image.write(ss.str());
}
delete[] calculated_values;
delete[] receive_buffer;
MPI_Finalize();
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment