# Fractals/kf-extras

< Fractals

kf-extras: c programs by Claude Heiland-Allen for

- manipulating output from Kalles Fraktaler 2
- the exponential map (aka log polar or mercator projection) convertor

# install[edit | edit source]

- git clone https://code.mathr.co.uk/kf-extras.git
- make

# Programs[edit | edit source]

Exemap: convert sequence of flat zoom images to the final location into an exponential map (unwrapped into log-polar coordinates)

- one long image
- side- by -side tiling

expmap n < x.txt > x.pgm # exponential map (log polar) with pseudo-de colour x.txt lists kfb files one per line, in order n is number of kfb files listed in x.txt

histogram d < x.kfb > x.pgm # histogram equalize (sort and search, O(N log N)) , d is density >= 1.0, affects the brightness curve

kfbtommit < x.kfb > x.mmit # convert to Mandel Machine iteration data format

pseudo-de < x.kfb > x.pgm # pseudo distance estimate colouring

rainbow < x.kfb > x.ppm # rainbow based on slope direction, plus pseudo-de

resize w h < x.kfb > x.kfb # resize to new (w,h) using bi-cubic interpolation

stretch < x.kfb > x.pgm # simple iteration count stretching

Scripts included ('bash' shell and common linux utilities required):

kfbtoogv.sh s work tmp

automatic movie maker with sound generation. Here

- s is desired movie length in seconds
- work is absolute path to dir containing
- *.kfb; tmp is absolute path to dir for output

it checks for the less-common programs it needs

# examples[edit | edit source]

## first[edit | edit source]

- parameters: http://mathr.co.uk/mandelbrot/2014-12-17_kf-extras_expmap_wire.kfr
- rendered from 98 640x360 kfb files, giving a 565x6075 image, downscaled 4x in GIMP for anti-aliasing.

# description[edit | edit source]

"How it works isn't too complex (most of the effort I put into making it stream data so it doesn't run out of memory for huge zoom sequences). The key loop that converts the flat image into a log-polar image runs like this:"

```
#pragma omp parallel for
for (int k = 0; k < expmap->circumference; ++k) {
double r = pow(0.5, 1.0 - expmap->row / (double) expmap->radius);
double t = 2 * pi * k / (double) expmap->circumference;
double i = r * cos(t) * expmap->height / 2.0 + expmap->width / 2.0;
double j = r * sin(t) * expmap->height / 2.0 + expmap->height / 2.0;
row[k] = kfb_get_nearest(expmap->kfb, i, j);
}
expmap->row++;
```

"Here width and height refer to the flat image, while circumference is the width of the output strip, and radius is the height of each section (one section is generated for each input file). The expmap->row variable is a counter that loops through concentric circles in the flat image, and there's some relatively simple maths to calculate the radius and angle for each point on the circle. Calculating the circumference and radius parameters is a bit more involved, here's the bit of code that does that with a few inline comments:"

```
expmap->circumference = expmap->height * pi / 2;
// 0.5 ^ (1 - 1 / radius) - 0.5 = |(0.5, 0)-(0.5*cos(t), 0.5*sin(t))|
// where t = 2 * pi / circumference
double t = 2 * pi / expmap->circumference;
double dx = 0.5 - 0.5 * cos(t);
double dy = 0.5 * sin(t);
double d = sqrt(dx * dx + dy * dy);
// (1 - 1 / radius) log 0.5 = log (d + 0.5)
// 1 - 1 / radius = log (d + 0.5) / log 0.5
// 1 / radius = 1 - log (d + 0.5) / log 0.5
expmap->radius = 1.0 / (1.0 - log(d + 0.5) / log(0.5));
```

The idea behind the maths is that ideally we want a uniform pixel aspect ratio, with pixels as square as possible. There's probably a neater and more direct way of calculating this, but I got it working so stopped looking for a better solution. Then the main loop steps through one row at a time (loading successive kfb files as necessary), keeping the previous row around to do the pseudo-de colouring I described in the previous blog post.

# key words[edit | edit source]

- flat image = image in linear-linear scale ( normal Cartesian coordinate) = standard flat view of part of the Mandelbrot set
- log-polar image ( expmap )