Fractal colors

In the first part of the tutorial we used a grayscale pallette. Now let's uncover the real beauty of chaos in full color.

HTML uses the Red-Green-Blue (RGB) model to describe colors. Each of the three components can have a value between 0 and 255 (one byte). So a combination of 0-255-0 gives us a strong green color (green has the maximum value while red and blue are zero). Its hexadecimal equivalent is "x00FF00": each component is determined by two hexadecimal digits (between x00 and xFF). The format can also be described by "xRRGGBB", where RR, GG and BB are the values of each component.

If the values of the components are equal, we go from black (x000000), through different shades of gray (eg. xA2A2A2) to white (xFFFFFF). Here's what it looks like:



Read this part only if you're curious why the left hand side of the pallette looks different: The first 16 combinations result in one hexadecimal digit per color, eg. decimal ten = hexadecimal "A", so the decimal combination R=10;G=10;B=10 results in hexadecimal "xAAA". HTML treats this as "shorthand" for "xAAAAAA" (each of the digits is doubled, even though mathematically we shoud have the value x0A0A0A. HTML's changing xA to xAA corresponds to a decimal change from 10 to 31!). While technically inaccurate, this is quite convenient in this case, because we get a rapid visual progression from black to white in the beginning of the scale, then we return to a dark gray followed by a much slower progression to white again. The initial image of Mandelbrot (without any zoom) happens to consist of a lot of pixels in the 0-15 range (the largest shapes in the darker shades of gray) and the inside has value of 255 (most of the pixels in the 16-254 range are in a relatively narrow areas around the fringes of the set and they only become better visible after zooming-in).

Now let's create a pallette where we assign the color index first to the red component, then to red and finally to blue. So the first 85 colors will be shades of red, colors 85-170 shades of green and 171-255 shades of blue:



The updates to the code are explained in the comments:

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<html>
<body>
<canvas id="myCanvaswidth="800height="800"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var pallette=[]; // the array that will hold the hex strings of the colors
 
for(x=0;x<256;x++) // the loop that creates the pallette
        {
        if(x<85)        // colors 0-84
                {
                r=x*3;
                g=0;
                b=0;
                }
        if(x>84&&x<171)        // colors 85-170
                {
                r=0;
                g=3*(x-84);
                b=0;
                }
        if(x>170)        // colors 170-255
                {
                r=0;
                g=0;
                b=3*(x-170);
                }
 
        r=r.toString(16); // conversion to hex
        g=g.toString(16);
        b=b.toString(16);        
 
        if (r.length==1r="0"+r// add a zero in front to change single-digit to double digit
        if (g.length==1g="0"+g;
        if (b.length==1b="0"+b;
 
        pallette[x]="#"+r+g+b// final hex string
        }
 
for(var x=0;x<200;x++)
        {
        for(var y=0;y<200;y++)
                {
                var i=0;
                var cx=-2+x/50;
                var cy=-2+y/50;
                var zx=0;
                var zy=0;                        
 
                        do
                                {
                                var xt=zx*zy;
                                zx=zx*zx-zy*zy+cx;
                                zy=2*xt+cy;
                                i++;
                                }
                        while(i<255&&(zx*zx+zy*zy)<4);
 
                        context.beginPath();
                        context.rect(x*4y*444);
                        context.fillStyle = pallette[i]; // the number of iterations determines the color
                        context.fill();
                }
        }
</script>
</body>
</html>


The set now looks like this:



This time, when the length of the hex string equals one, we add a zero in front of it, to avoid the shorthand. While mathematically more precise than the grayscale one, this pallette results in a less appealing image of the entire set, because large areas appear simply black. In reality those large shapes are still there in a slightly lighter shade of gray, but our eyes are not able to notice these tiny differences. The shades of red, green and blue are tiny and only visible after zooming in:





Here's another pallette, where by trial-and-error I came up with a complicated math formula resulting in a rapid transition from black to red in the very first part and then gradual transitions to yellow to blue:



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
        for(x=0;x<256;x++) // the loop that creates the pallette
        {
        if(x<31)
                {
                r=255-40*Math.floor(1/(x/10));
                g=0;
                b=0;
                }
        if(x>30&&x<131)
                {
                r=255;
                g=Math.floor(2.1*(x-30));
                b=0;
                }
        if(x>130)
                {
                r=255-Math.floor((x-130)*2);
                g=255-Math.floor((x-130)*2);
                b=Math.floor((x-130)*2);
                }


Here's the result:



I simply kept changing the numbers in the pallette formula almost randomly until I got something I liked. Try experimenting with other functions (sin/cos, parabolic, random) to come up with interesting pallettes.

Check out the tutorial on Julia fractals and how to animate them in 32 lines of code.



Fractals in Excel
3d fractal in Blender Python



Your first program in JavaScript: you need 5 minutes and a notepad

Tutorial - interactive, animated sprites in JavaScript