Improvement to my Mandelbrot set code
Asked Answered
P

1

7

I have the following Mandelbrot set code in C. I am doing the calculation and creating a .ppm file for the final fractal image. The point is that my fractal image is upside down, meaning it is rotated by 90 degrees. You can check it by executing my code: ./mandel > test.ppm

On the other hand, I also want to change the colours. I want to achieve this fractal image:

enter image description here

My final issue is that my code doesn't check the running time of my code. I have the code for this part too, but when code execution finishes it doesn't print the running time. If someone can make the appropriate changes to my code and help me achieve this fractal image, and make elapsed time displayed I would be glad.

#include <math.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

void color(int red, int green, int blue)
{
    fputc((char)red, stdout);
    fputc((char)green, stdout);
    fputc((char)blue, stdout);
}

int main(int argc, char *argv[])
{
    int w = 600, h = 400, x, y; 
    //each iteration, it calculates: newz = oldz*oldz + p, where p is the current pixel, and oldz stars at the origin
    double pr, pi;                   //real and imaginary part of the pixel p
    double newRe, newIm, oldRe, oldIm;   //real and imaginary parts of new and old z
    double zoom = 1, moveX = -0.5, moveY = 0; //you can change these to zoom and change position
    int maxIterations = 1000;//after how much iterations the function should stop

    clock_t begin, end;
    double time_spent;

    printf("P6\n# CREATOR: E.T / mandel program\n");
    printf("%d %d\n255\n",w,h);

    begin = clock();

    //loop through every pixel
    for(x = 0; x < w; x++) 
    for(y = 0; y < h; y++)
    {
        //calculate the initial real and imaginary part of z, based on the pixel location and zoom and position values
    pr = 1.5 * (x - w / 2) / (0.5 * zoom * w) + moveX;
        pi = (y - h / 2) / (0.5 * zoom * h) + moveY;
        newRe = newIm = oldRe = oldIm = 0; //these should start at 0,0
        //"i" will represent the number of iterations
        int i;
        //start the iteration process
        for(i = 0; i < maxIterations; i++)
        {
            //remember value of previous iteration
            oldRe = newRe;
            oldIm = newIm;
            //the actual iteration, the real and imaginary part are calculated
            newRe = oldRe * oldRe - oldIm * oldIm + pr;
            newIm = 2 * oldRe * oldIm + pi;
            //if the point is outside the circle with radius 2: stop
            if((newRe * newRe + newIm * newIm) > 4) break;
        }

        color(i % 256, 255, 255 * (i < maxIterations));

    }

    end = clock();

    time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf("Elapsed time: %.2lf seconds.\n", time_spent);

    return 0;
}
Puga answered 20/4, 2013 at 19:10 Comment(0)
G
9

Part 1: You need to swap the order of your loops to:

for(y = 0; y < h; y++)
for(x = 0; x < w; x++)

That will give you the correctly oriented fractal.

Part 2: To get the time to print out, you should print it to stderr since you are printing the ppm output to stdout:

fprintf(stderr, "Elapsed time: %.2lf seconds.\n", time_spent);

Part 3: To get a continuous smooth coloring, you need to use the Normalized Iteration Count method or something similar. Here is a replacement for your coloring section that gives you something similar to what you desire:

    if(i == maxIterations)
        color(0, 0, 0); // black
    else
    {
        double z = sqrt(newRe * newRe + newIm * newIm);
        int brightness = 256. * log2(1.75 + i - log2(log2(z))) / log2(double(maxIterations));
        color(brightness, brightness, 255);
    }

It isn't quite there because I kind of did a simple approximate implementation of the Normalized Iteration Count method.

Mandelbrot using some semi-continuous coloring

It isn't a fully continuous coloring, but it is kind of close.

Gordan answered 20/4, 2013 at 21:13 Comment(4)
Thanks! It solved my problem. But there is a small cast error regarding parenthesis in the last part of your code. If you could correct it for the sake of other people, it could be great.Puga
@erkant, Do you mean double(maxIterations)? It works fine for me with gcc. Is it something else?Gordan
Yes, I was talking about it. It didn't work for me, I had to use parenthesis like ((double)maxIterations).Puga
Ok, maybe I'm using a newer/different compiler than you. I usually code in C++ so maybe this didn't used to be valid in C.Gordan

© 2022 - 2024 — McMap. All rights reserved.