Phillip Trelford's Array

POKE 36879,255

Fractal Zoom in Colour

A few years back I put together a simple Fractal Zoom in Silverlight using gray scales.

Time for a little makeover with color:


Hold down the mouse button over the Mandelbrot and move the mouse to highlight a rectangle, then release the mouse button to zoom in on that area.

Implementation

To get a nice colour progression I used the HSB color circle:

let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5

Then created a colour lookup table using a list comprehension:

[|for i in 0..maxIteration ->
    let n = float i / float maxIteration
    let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5
    let H = H - floor H
    let r,g,b = RGB.FromHSL(H,S,L)
    0xff000000 + (r <<< 16) + (g <<< 8) + b|]

For the HSL to RGB conversion I converted Colin Eberhardt’s accepted Stack Overflow answer from C# to F#:

C# F#
double v;
double r, g, b;
if (A > 1.0)
A = 1.0;

r = L;   // default to gray
g = L;
b = L;
v = 
   (L <= 0.5) 
   ? (L * (1.0 + S)) 
   : (L + S - L * S);
if (v > 0)
{
    double m;
    double sv;
    int sextant;
    double fract, vsf, mid1, mid2;

    m = L + L - v;
    sv = (v - m) / v;
    H *= 6.0;
    sextant = (int)H;
    fract = H - sextant;
    vsf = v * sv * fract;
    mid1 = m + vsf;
    mid2 = v - vsf;
    switch (sextant)
    {
       case 0:
        r = v;
        g = mid1;
        b = m;
        break;
       case 1:
        r = mid2;
        g = v;
        b = m;
        break;
       case 2:
        r = m;
        g = v;
        b = mid1;
        break;
       case 3:
        r = m;
        g = mid2;
        b = v;
        break;
       case 4:
        r = mid1;
        g = m;
        b = v;
        break;
       case 5:
        r = v;
        g = m;
        b = mid2;
        break;
    }
}
ColorRGB rgb = new ColorRGB();
rgb.R = Convert.ToByte(r * 255.0f);
rgb.G = Convert.ToByte(g * 255.0f);
rgb.B = Convert.ToByte(b * 255.0f);
rgb.A = Convert.ToByte(A * 255.0f);
return rgb;
let v = 
    if (L <= 0.5) 
    then (L * (1.0 + S)) 
    else (L + S - L * S)
if v > 0.0 then                
    let m = L + L - v;
    let sv = (v - m) / v;
    let H = H * 6.0;
    let sextant = int H
    let fract = H - float sextant
    let vsf = v * sv * fract;
    let mid1 = m + vsf;
    let mid2 = v - vsf;
    match sextant with
    | 0 -> v, mid1, m
    | 1 -> mid2, v, m
    | 2 -> m, v, mid1
    | 3 -> m, mid2, v
    | 4 -> mid1, m, v
    | 5 -> v, m, mid2
    | _ -> L, L, L
else L, L, L
|> fun (r,g,b) –> 
   byte(r*255.),
   byte(g*255.),
   byte(b*255.)

Voila, happy zooming :)

Comments are closed