Fractal Coloring
Fractal in 24bit colors
When I began fractal plotting in the early 1980s using Apple III and its Pascal compiler, there were only two colors, black and white, available and the coloring job was quite simple. Because fractal plotting was such a novel idea back then, I was genuinely excited every time I saw an output fractal finally emerged on the little computer screen after days of computation, even though the picture was usually boring by today's standard.
As I upgraded my desktop computers and compilers a few times since then, the color depth improved from socalled 1bit colors (with 2^{1} = 2 available colors) to 4bit colors (2^{4} = 16 colors) and then to 8bit colors (2^{8} = 256 colors), allowing me to plot more colorful fractals. In the late 1990s when the university I worked at equipped my office with a PC with a 24bit "true color" capacity that allowed me to use whopping 2^{24} = 16,777,216 colors, coloring was no longer simple and I had to develop a purely mathematical way of coloring fractals to take full advantage of the new hardware.
Written below is the coloring method I have been using since then. Because good human eyes can distinguish "only" up to 10 million colors out of the 16 million+ colors, I expect that the 24bit colors would stay with us for a long time without a substantial change regardless of the progress in computer technologies.
We begin our discussion with a few preliminary ideas needed for our fractal coloring.
PreColored Fractals. When we plot a fractal by, say, the divergence scheme and a dynamical system like the Mandelbrot equation z_{n+1} = z_{n}^{2} + p, we first compute an array of nonnegative integers d(i, j) over the canvas in pixel coordinates (i, j) by the formula:
(†0) d(i, j) = the least iteration index m < M such that the orbit z_{n} of p = (i, j) satisfies z_{m} > T,
if such m exists, and d(i, j) = M, otherwise. Here, M is a prescribed maximum number of iterations and T is an appropriate threshold value. Thus, each d(i, j) represents, unless d(i, j) = M, the number of iterations m or "time" it takes for the orbit z_{n} of p = (i, j) to escape from the circle of radius T before taking a long journey toward ∞.
We call an array (or matrix) of nonnegative integers d(i, j) over a canvas (i, j) a precolored fractal if it can be converted to colors that show a visual fractal on the canvas. The array d(i, j) given by (†0) is an example of precolored fractals.
Example 1. As explained in the divergence scheme, we iterate the Mandelbrot equation for each pixel p = (i, j) using M = 500 and T = 2 and compute an array d(i, j) using (†0). For example, if 310 happens to be the least (i.e., the first) iteration index m such that z_{m} > 2, set d(i, j) = 310 and stop the iteration for this pixel so as to thwart the computer from wasting its runtime. If we color the pixels (i, j) black or white depending upon the parity (evenness or oddness) of d(i, j), we get a fractal similar to Figure 1 below.
It is often convenient to decompose the canvas into a disjoint union of blocks (subsets) and "flag" every block by another array, say, f(i, j) of smaller nonnegative integers such as bits, 0 and 1, or bytes, 0  255.
For example, for each pixel (i, j) in the canvas of Example 1, set f(i, j) = 0 if d(i, j) < M, and f(i, j) = 1, otherwise. Thus, the block flagged 1 is where the Mandelbrot set lies and the block flagged 0 corresponds to the complement of the Mandelbrot set consisting of the parameters whose orbits diverge to ∞. If we color each pixel (i, j) in the block (flagged) 0 red or black depending upon the parity of d(i, j), and color (i, j) in the block 1 white, we get a fractal similar to Figure 2.1 shown in Stories About Fractal Plotting.
If k is a positive integer and ε is a small real number such as 10^{6}, then the convergence scheme with period index k also gives rise to an array d(i, j) of nonnegative integers by the formula:
(†k) d(i, j) = the least iteration index m < M such that the orbit z_{n} of p = (i, j) satisfies z_{m+k}  z_{m} < ε,
if such m exists, and d(i, j) = M, otherwise. When we apply a combination of the formulas (†0) and (†k) on computing a precolored fractal, the block decomposition becomes especially useful in keeping the matter organized.
Example 2. Plotting a reasonably detailed "global" multicolor image of the Mandelbrot set requires more than a dozen formulas (†0), (†1), (†2), · · · as shown in the following steps:
Step 1. Apply the divergence scheme on the entire canvas and extract the block consisting of the pixels whose orbits diverge to ∞. Flag the block 0 by setting f(i, j) = 0 and compute d(i, j) on this block using the formula (†0).
Step 2. Apply the convergence scheme with period index 1 on the remainder of the canvas and extract the block consisting of the pixels whose orbits converge to a 1cycle (a point). Flag the block 1 and compute d(i, j) on this block using (†1).
Step 3. Apply the convergence scheme with period index 2 on the remainder of the canvas and extract the block consisting of the pixels whose orbits converge to a 2cycle. Flag the block 2 and compute d(i, j) on this block using (†2).
Repeat the process up to, say, Step 20, and set d(i, j) = M and f(i, j) = 20 for the remaining pixels (i, j) untouched by Step 1 though Step 20.
Plotting a visual fractal becomes easy once the block decomposition of the canvas is done: If we color the block (flagged) 0 like in Figure 1, the block (flagged) 1 red, the blocks 2 and 3 orange, the block 4 purple, etc., we get Figure 2 shown above. Later, we'll upgrade it to Figures 7 and 8 using 24bit colors.
Remark. The method in Example 2 is a brute force algorithm and requires a long computing time. It can be made more efficient, but we probably don't plot a global image of the Mandelbrot set very often. By comparison, Julia sets are much simpler to deal with.
Example 3. Consider the dynamical system
(1)
z_{n+1 }= f_{p}(z_{n}) = p(1  z_{n}^{2}) z_{n }
with the fixed parameter p = (1.18, 0.376). Figure 3 on the left is a Julia fractal and its precolored fractal is given by Steps 1 and 2 of the previous example plus the last step of setting d(i, j) = M and f(i, j) = 2 for the remaining pixels (i, j) untouched by Steps 1 and 2.
The block (or the subset of the canvas) flagged 2 happens to depict the Julia set of p separating its exterior (which is the block 0 colored gray and white) from its interior (which is the block 1 colored black and yellow).
Computing a precolored fractal is generally a timeconsuming process as it often involves millions of iterations of the dynamical system, one iteration process for each pixel on the canvas. So, it is important that we store it in the hard disk.
Fractal coloring, on the other hand, occupies a small part in terms of the computer's runtime, but it is reminiscent of painting a newly built house and can improve or ruin the entire effort. We can also make different images from the same precolored fractal by applying different colors. For example, the first and second images, called "Racing Elephants" and "Flock of Owls," are based on the same precolored fractal, which we can see through the third image. (They are painted by 24bit colors by the method we have not yet discussed.)
The Color Cube. Red, green, and blue are the primary colors of light―they can be combined in different proportions to make all other colors. For example, red light and green light added together are seen as yellow light. This additive color system is used by light sources, such as televisions and computer monitors, to create a wide range of colors. When different proportions of red, green, and blue light enter your eye, your brain is able to interpret the different combinations as different colors. ... From HarvardSmithsonian Center for Astrophysics.
Mathematically speaking, the 24bit colors we mentioned earlier are packed in the 3D color cube shown in Figure 5 below. It is given by the RGB coordinate system with R, G and Baxes representing the three primary colors of red, green and blue, respectively. The Raxis, for example, consists of 2^{8} = 256 shades of red, namely,
black = (0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0), · · ·, (255, 0, 0) = red,
and likewise for the G and Baxes with green = (0, 255, 0) and blue = (0, 0, 255). (0, 0, 0), which is black, is the origin of the coordinate system and white = (255, 255, 255) is the vertex of the color cube opposite from the origin (black).
Just like in the Cartesian 3D space with x, y, zaxes, therefore, each color in the color cube is represented by an ordered triple (R, G, B) of integers between 0 and 255, called bytes; hence the total number of colors in the color cube is
256^{ 3} = 2^{24} = 16,777,216 as we have seen.
The color cube shows, for example,
yellow = (255, 255, 0) = (255, 0, 0) + (0, 255, 0) = red + green,
purple = (255, 0, 255) = (255, 0, 0) + (0, 0, 255) = red + blue,
white = (255, 255, 255) = red + green + blue,
and orange is the midpoint (average) between red and yellow, namely 0.5 x [(255, 0, 0) + (255, 255, 0)] =(255, 128, 0). Because black = (0, 0, 0), a color is generally darker when all of its components are closer to 0. For example, a brownish color is given by darkening the components of orange like 0.7 x (255, 128, 0) = (179, 90, 0).
Thus, we get a color by adding two colors or multiplying a color by a nonnegative real number as long as all of the color components stay as bytes. Here, the noninteger components are always rounded to bytes.
Line Segments in the Color Cube. Suppose C_{1} = (R_{1}, G_{1}, B_{1}) and C_{2} = (R_{2}, G_{2}, B_{2}) are two colors in the color cube. Then by the line segment from C_{1} to C_{2}, we mean the set of all colors C = (R, G, B) satisfying the parametric equations
(☆) R = (1  t) x R_{1} + t x R_{2}, G = (1  t) x G_{1} + t x G_{2},
B = (1  t) x B_{1} + t x B_{2},
where the parameter t satisfies 0 < t < 1. Note that if t = 0, C = C_{1}, and if t = 1, C = C_{2}, so we imagine that C moves along the line segment by gradually changing its color from C_{1} to C_{2} as "time" t progresses from 0 to 1.
Applications. We have seen that a precolored fractal is an array of nonnegative integers d(i, j) over a canvas comprising pixels (i, j) and that the canvas is decomposed into a disjoint union of finitely many blocks. The canvas may have only one block as is the case in Example 1 or as many as we want to handle in our computer program as shown in Example 2. If the canvas has two or more blocks, we flag each block by a unque number f(i, j) like f(i, j) = 5 for all pixels belonging to the block; see Example 2.
So, given a precolored fractal d(i, j) over a canvas, let S be any of the blocks in the canvas and let n_{1} and n_{2} be the minimum and maximum of the integers d(i, j) over S, respectively. Suppose we wish to paint all pixels in S using the colors in the line segment between colors C_{1} and C_{2}. Assume also that, in the following discussion, all pixels (i, j) belong to the block S.
For any integer n = d(i, j), we have n_{1} ≤ n ≤ n_{2}, so, normalize n to the range between 0 and 1 by setting
(2) s = (n  n_{1})/(n_{2}  n_{1}),
and then let
(3) t = s
in (☆). Observe that if n = n_{1}, t = s = 0, so, C = C_{1}, and if n = n_{2}, t = s = 1, so, C = C_{2}, Therefore, as n = d(i, j) increases from n_{1} to n_{2}, the corresponding color C, which we use to paint the pixels (i, j), changes from C_{1} to C_{2}. Note that usually numerous pixels (i, j) in S are mapped onto a single number n = d(i, j) and are painted by the color C.
For example, Figure 6 on the left shows how the color of the pixels (i, j) changes with n = d(i, j) from red to black. Because of (2) and (3), t is a linear function of n.
Example 4. (Continuation of Example 2) We have seen that the canvas for the Mandelbrot set is decomposed into 21 blocks named (or flagged) block 0 through block 20. Block 0 is the complement of the Mandelbrot set, block 1 the interior of the cardioid, block 2 the interior of the largest circular disk, block 3 the interior of the second largest disks (there are two of them), and so on so forth; see Figure 2.
Painting the Mandelbrot set using 24bit colors is now easy as the precolored fractal d(i, j) has already been computed over the entire canvas. We use the linear coloring of Figure 6 to paint the block 1 (the interior of the cardioid) by the color change from red to black and similarly paint the block 0 by the color change from black to green, the blocks 2 and 3 from orange to black, the block 4 from purple to black, etc. This gives us Figure 7 shown below.
We note in Figure 7 that the interior of the cardioid, for instance, has its vast area painted by brighter red despite the fact that the coloring is linear, and that is because the higher numbers d(i, j) are concentrated near the boundary of the Mandelbrot set. By the way, the block numbers 1, 2, 3, · · ·, coincide with the numbers in Wikipedia's Periodicity Diagram and are very useful in plotting various Julia sets.
We also note that if we change the equation (3) by
(4) t = 1  s
then we get another linear coloring scheme shown by Figure 9 on the left, where color changes from C_{2} to C_{1} with n.
Now, using the linear coloring schemes of Figures 6 and 9, it is fairly easy to program a computer to generate the periodic coloring schemes shown in Figure 10 below. Here, the color changes between yellow and brown instead of red and black, and the coloring scheme on the right is given by squaring the function on the left to change the "V function" to the parabolic "U function." In fact, we can use any power function instead of squaring to change the way color oscillates between yellow and brown.
Example 5. (Continuation of Example 3) Figure 3 depicts the Julia set of Example 3 whose exterior (block 0) and interior (block 1) are painted by 2bit colors. By comparison, Figure 11 given below illustrates various ways of painting the Julia set using 24bit colors. The interior of the Julia set in the first two images are given by the periodic linear and parabolic coloring schemes (with a different frequency) of Figure 10, respectively.
The interior of the Julia set in the last two images of Figure 11 are painted by the periodic coloring schemes given by the diagrams below. They involve four colors, blue, yellow, orange and red, instead of two colors, yellow and brown.
Finally, Figure 8 shows that we can partition each block into subblocks and apply different coloring on each subblock. With patience, we can develop a wider variety of coloring schemes and certainly paint immensely colorful fractals.

