Paste: c++ mandelbrot initial version

Author: kssreeram
Mode: c++
Date: Thu, 24 Sep 2009 08:45:19
Plain Text |
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>

struct Complex {
    double r, i;

    Complex(double r, double i)
        : r(r), i(i) {}

    Complex operator+(const Complex &a) {
        return Complex(r+a.r, i+a.i);
    }
    Complex operator*(const Complex &a) {
        return Complex(r*a.r - i*a.i, r*a.i + i*a.r);
    }
    double absq() {
        return r*r + i*i;
    }
};

struct RGB {
    unsigned char rgb[3];

    RGB(unsigned char r, unsigned g, unsigned b) {
        rgb[0] = r;
        rgb[1] = g;
        rgb[2] = b;
    }
};

struct HSV {
    double h, s, v;

    HSV(double h, double s, double v)
        : h(h), s(s), v(v) {}

    int hi() {
        return int(floor(h/60)) % 6;
    }
    double f() {
        return h/60 - hi();
    }
    double p() {
        return (1-s)*v;
    }
    double q() {
        return (1 - f()*s)*v;
    }
    double t() {
        return (1 -((1 - f())*s))*v;
    }

    static RGB makeRGB(double r, double g, double b) {
        return RGB((unsigned char)(r*255),
                   (unsigned char)(g*255),
                   (unsigned char)(b*255));
    }

    RGB toRGB() {
        switch (hi()) {
        case 0 : return makeRGB(v, t(), p());
        case 1 : return makeRGB(q(), v, p());
        case 2 : return makeRGB(p(), v, t());
        case 3 : return makeRGB(p(), q(), v);
        case 4 : return makeRGB(t(), p(), v);
        default :
            return makeRGB(v, p(), q());
        }
    }
};

int width = 640;
int height = 480;
int maxColor = 360;
int maxIterations = 40;
double zoomFact = 0.8;
double center = -0.65;

double xInc = width / (200000 * zoomFact);
double yInc = height / (150000 * zoomFact);

double sat = 0.85;
double val = 0.85;

std::vector<RGB> makeColorMap(int nbCols)
{
    std::vector<RGB> out;
    for (int i = 0; i < nbCols; ++i) {
        out.push_back(HSV((360.0*i)/(nbCols+1), sat, val).toRGB());
    }
    return out;
}

std::vector<RGB> colorMap = makeColorMap(std::min(maxIterations, maxColor));

Complex c(int i, int j) {
    return Complex(xInc*i + center - xInc*width/2,
                   yInc*j - yInc*height/2);
}

int pixel(Complex c) {
    Complex z = Complex(0.0, 0.0);
    for (int i = maxIterations; i >= 0; --i) {
        z = z*z + c;
        if (z.absq() >= 4.0)
            return i;
    }
    return -1;
}

RGB black = RGB(0, 0, 0);

RGB color(int iterations) {
    if (iterations == -1)
        return black;
    else
        return colorMap[iterations % colorMap.size()];
}

void render(FILE *out) {
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; ++i) {
            RGB rgb = color(pixel(c(i, j)));
            fwrite(&rgb.rgb, 1, 3, out);
        }
    }
}

void writePPMHeader(FILE *out) {
    char buf[30];
    sprintf(buf, "P6\n%d %d\n255\n", width, height);
    fwrite(buf, 1, strlen(buf), out);
}

void run() {
    FILE *out = fopen("out.ppm", "wb");
    if (!out) {
        printf("unable to open out.ppm\n");
        return;
    }
    writePPMHeader(out);
    render(out);
    fclose(out);
}

int main() {
    run();
    return 0;
}

Annotation: improved inner loop

Author: kssreeram
Mode: c++
Date: Thu, 24 Sep 2009 08:55:22
Plain Text |
void render(FILE *out) {
    int n = width * height * 3;
    unsigned char *buf = new unsigned char[n];
    unsigned char *ptr = buf;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; ++i) {
            RGB rgb = color(pixel(c(i, j)));
            *(ptr++) = rgb.rgb[0];
            *(ptr++) = rgb.rgb[1];
            *(ptr++) = rgb.rgb[2];
        }
    }
    fwrite(buf, 1, n, out);
    delete [] buf;
}

New Annotation

Summary:
Author:
Mode:
Body: