C++ Fractal Plotter

articles ✒ cpp-fractals

This article follows on from my original article which showed how to use Haskell to render fractals. The machine code produced by the Haskell compiler ghc proved too slow so I rewrote the Haskell program in C++.

Here's what the output of the program should look like (rendered at 3200x3200 then scaled down with The GIMP):

Mandelbrot fractal

 
#include <vector>
struct colour { unsigned char r,g,b; };
 
using namespace std;
 
inline int mandelbrot(double x, double y)
{
    double zr = 0.0, zi = 0.0, tmp = 0.0;
    int iter = 0;
    while (iter < 255)
    {
        tmp = zr;
        zr = (zr*zr) + x - (zi*zi);
        zi = (zi * 2.0 * tmp) + y;
 
        if ((zr * zr) + (zi * zi) > 4) break;
        ++iter;
    }
    return iter;
}
 
 
vector<int> evaluateMandelbrot2D(double x1, double x2, double y1, double y2, int width, int height)
{
    vector<int> output(width * height);
    int pixel = 0;
 
    double xscale = (x2 - x1) / (width - 1.0);
    double yscale = (y2 - y1) / (height - 1.0);
 
    for (int y= 0; y < height; ++y)
    {
        printf("%d/%d\n", y, height);
        for (int x = 0; x < width; ++x)
        {
            output.at(pixel) = mandelbrot(x1 + (x * xscale), y1 + (y * yscale));
            ++pixel;
        }
    }
    return output;
}
 
vector<colour> colourimage(vector<int> im)
{
    vector<colour> colouredim(im.size());
    for (int pixel = 0; pixel < im.size(); pixel++)
    {
        colour col = {im[pixel], im[pixel], im[pixel]};
        colouredim[pixel] = col;
    }
    return colouredim;
}
 
void savePPM(int width, int height, vector<colour> im, FILE* fh)
{
    vector<char> imout(width * height);
    int pixels = width * height;
    fprintf(fh, "P3\n%d\n%d\n255\n", width, height);
    for (int pixel = 0; pixel < pixels; ++pixel)
    {
        fprintf(fh, "%d %d %d\n", im[pixel].r, im[pixel].g, im[pixel].b);
    }
}
 
int main()
{
    FILE *fh = fopen("mandelbrot.ppm", "w");
    savePPM(3200, 3200, colourimage(evaluateMandelbrot2D(-3.0, 3.0, -3.0, 3.0, 3200, 3200)), fh);
    fclose(fh);
    return 0;
}
 

comment on this page