c++mandelbrot

Threaded Mandelbrot program C++


To preface this: I'm currently a first-year student who was allowed to enroll in some second-year classes. Because of this, I'm currently wrangling a language (C++) that I haven't really had the time to learn (First-years mostly learn C#), so this code might not be pretty.

Our assignment is twofold. First, we need to write a program that outputs a Mandelbrot image in a PPM. To achieve this, I've followed a Youtube tutorial here.

The second part of the assignment is to make the program multithreaded. Essentially, the program is supposed to use 4 threads that each draw a quarter of the image.

To this end I have altered the code from the video tutorial, and converted the main to a method. Now, I'm trying to properly make the first quarter of the image. I figured the way to do this was to adjust

        for (int y = 0; y < imageHeight; y++) //Rows!
        {
           for (int x = 0; x < imageWidth; x++) //Columns! (pixels in every row)
           {

to

        for (int y = 0; y < halfHeight; y++) //Rows!
        {
           for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
           {

However, instead of drawing the top left quarter as I suspected, the program drew along the full width, repeating itself after the halfway mark of the image width was reached, and only drew along a quarter of the height (see image)

As I like to learn from my mistakes, I'd love to know what exactly is going wrong here.

Thank you for helping a programming greenhorn out :)

Full program code below.

#include "stdafx.h"
#include <fstream>
#include <iostream>

int imageWidth = 512, imageHeight = 512, maxN = 255, halfWidth = 256, halfHeight = 256;
double minR = -1.5, maxR = 0.7, minI = -1.0, maxI = 1.0;
std::ofstream f_out("output_image.ppm");

int findMandelbrot(double cr, double ci, int max_iterations)
{
    int i = 0;
    double zr = 0.0, zi = 0.0;
    while (i < max_iterations && zr * zr + zi * zi < 4.0)
    {
        double temp = zr * zr - zi * zi + cr;
        zi = 2.0 * zr * zi + ci;
        zr = temp;
        i++;
    }

    return i;
}

double mapToReal(int x, int imageWidth, double minR, double maxR)
{
    double range = maxR - minR;
    return x * (range / imageWidth) + minR;
}

double mapToImaginary(int y, int imageHeight, double minI, double maxI)
{
    double range = maxI - minI;
    return y * (range / imageHeight) + minI;
}

void threadedMandelbrot() 
{
    for (int y = 0; y < halfHeight; y++) //Rows!
    {
        for (int x = 0; x < halfWidth; x++) //Columns! (pixels in every row)
        {
            //... Find the real and imaginary values of c, corresponding
            //      to that x,y pixel in the image
            double cr = mapToReal(x, imageWidth, minR, maxR);
            double ci = mapToImaginary(y, imageHeight, minI, maxI);
            //... Find the number of iterations in the Mandelbrot formula
            //      using said c.
            int n = findMandelbrot(cr, ci, maxN);

            //... Map the resulting number to an RGB value.
            int r = (n % 256);
            int g = (n % 256);
            int b = (n % 256);

            //... Output it to the image
            f_out << r << " " << g << " " << b << " ";
        }
        f_out << std::endl;
    }

}


int main()
{
    //Initializes file
    f_out << "P3" << std::endl;
    f_out << imageWidth << " " << imageHeight << std::endl;
    f_out << "256" << std::endl;

    //For every pixel...
    threadedMandelbrot();
    f_out.close();
    std::cout << "Helemaal klaar!" << std::endl;
    return 0;
}

Solution

  • Your are calculating only a quarter of the image, so you have to set the dimension of that to halfHeight, halfWidth or fill the file with zeroes. When the image viewer reads the file, it shows two lines of it in a single line of pixels untill it reaches the end of the file, at a quarter of the picture height.

    To fix the problem you just have to calculate the other three quarters of the image, but I suggest you to seperate the calc function from the file writing function: do the threaded calcs putting the result in an array (std::array or std::vector), look up the right color and then write to file.