Which color gradient is used to color mandelbrot i

2019-01-31 23:52发布

At the wikipedia's Mandelbrot page there are really beautiful generated images of the Mandelbrot set.

Detail Mandelbrot

I also just implemented my own mandelbrot algorithm. Given n is the number of iterations used to calculate each pixel, I color them pretty simple from black to green to white like that (with C++ and Qt 5.0):

QColor mapping(Qt::white);
if (n <= MAX_ITERATIONS){
    double quotient = (double) n / (double) MAX_ITERATIONS;
    double color = _clamp(0.f, 1.f, quotient);
    if (quotient > 0.5) {
        // Close to the mandelbrot set the color changes from green to white
        mapping.setRgbF(color, 1.f, color);
    }
    else {
        // Far away it changes from black to green
        mapping.setRgbF(0.f, color, 0.f);
    }
}
return mapping;

My result looks like that:

enter image description here

I like it pretty much already, but which color gradient is used for the images in Wikipedia? How to calculate that gradient with a given n of iterations?

(This question is not about smoothing.)

3条回答
在下西门庆
2楼-- · 2019-01-31 23:54

Well, I did some reverse engineering on the colours used in wikipedia using the Photoshop eyedropper. There are 16 colours in this gradient:

  R   G   B
 66  30  15 # brown 3
 25   7  26 # dark violett
  9   1  47 # darkest blue
  4   4  73 # blue 5
  0   7 100 # blue 4
 12  44 138 # blue 3
 24  82 177 # blue 2
 57 125 209 # blue 1
134 181 229 # blue 0
211 236 248 # lightest blue
241 233 191 # lightest yellow
248 201  95 # light yellow
255 170   0 # dirty yellow
204 128   0 # brown 0
153  87   0 # brown 1
106  52   3 # brown 2

Simply using a modulo and an QColor array allows me to iterate through all colours in the gradient:

if (n < MAX_ITERATIONS && n > 0) {
    int i = n % 16;
    QColor mapping[16];
    mapping[0].setRgb(66, 30, 15);
    mapping[1].setRgb(25, 7, 26);
    mapping[2].setRgb(9, 1, 47);
    mapping[3].setRgb(4, 4, 73);
    mapping[4].setRgb(0, 7, 100);
    mapping[5].setRgb(12, 44, 138);
    mapping[6].setRgb(24, 82, 177);
    mapping[7].setRgb(57, 125, 209);
    mapping[8].setRgb(134, 181, 229);
    mapping[9].setRgb(211, 236, 248);
    mapping[10].setRgb(241, 233, 191);
    mapping[11].setRgb(248, 201, 95);
    mapping[12].setRgb(255, 170, 0);
    mapping[13].setRgb(204, 128, 0);
    mapping[14].setRgb(153, 87, 0);
    mapping[15].setRgb(106, 52, 3);
    return mapping[i];
}
else return Qt::black;

The result looks pretty much like what I was looking for:

Mandelbrot set

:)

查看更多
叛逆
3楼-- · 2019-01-31 23:56

I believe they're the default colours in Ultra Fractal. The evaluation version comes with source for a lot of the parameters, and I think that includes that colour map (if you can't infer it from the screenshot on the front page) and possibly also the logic behind dynamically scaling that colour map appropriately for each scene.

查看更多
兄弟一词,经得起流年.
4楼-- · 2019-02-01 00:13

The gradient is probably from Ultra Fractal. It is defined by 5 control points:

Position = 0.0     Color = (0,   7,   100)
Position = 0.16    Color = (32,  107, 203)
Position = 0.42    Color = (237, 255, 255)
Position = 0.6425  Color = (255, 170, 0)
Position = 0.8575  Color = (0,   2,   0)

where position is in range [0, 1] and color is RGB from 0 to 255.

The catch is that it is not linear gradient. The interpolation between points is cubic (or something similar). Following image shows the difference between linear and Monotone cubic interpolation:

Linear vs cubic gradient

As you can see the the cubic is much smoother and "prettier". I used monotone cubic interpolation to avoid "overshooting" of color range that can be caused by basic cubic. Monotone cubic ansures that interpolated values are always in the range of input points (0-255).

I use following code to compute the color based on iteration i:

double size = Math.Sqrt(re * re + im * im);
double smoothed = Math.Log(Math.Log(size) * ONE_OVER_LOG2) * ONE_OVER_LOG2;
int colorI = (int)(Math.Sqrt(i + 1 - smoothed) * gradient.Scale + gradient.Shift) % colors.Length;
Color color = colors[colorI];

Where i is the diverged iteration number, re and im are diverged coordinates, gradient.Scale is 256, gradient.Shift is 0 and the colors is array with pre-discretized gradient showed above. Its length is usually 2048.

查看更多
登录 后发表回答