分形/kf-extras
外观
< 分形
kf-extras:Claude Heiland-Allen 为
- git clone https://code.mathr.co.uk/kf-extras.git
- make
OpenEXR[1]
sudo apt install libopenexr-dev
Exemap:将一系列平坦缩放图像转换为最终位置,并将其转换为指数映射(展开到对数极坐标中)
- 一张长图像
- 并排平铺
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
包含的脚本(需要 'bash' shell 和常用的 linux 实用程序)
kfbtoogv.sh s work tmp
带有声音生成的自动电影制作器。这里
- s 是所需的电影长度,以秒为单位
- work 是包含
- *.kfb 的目录的绝对路径;tmp 是输出目录的绝对路径
它会检查它需要的不太常见的程序
kfb-to-exr test.kfb test.exr exrheader test.exr // utility to print an OpenEXR image file's header pnmcat -tb *.exr > *.ppm // file test.exr
检查 exr 文件的标头
file fraktaler-3.00000036.exr:
结果
file format version: 2, flags 0x0 Fraktaler3 (type string): "program = "fraktaler-3" version = "0-414-g61fa84a" location.real = "-1.748764520194788535" location.imag = "3e-13" location.zoom = "1.0000000e15" bailout.iterations = 262144 bailout.maximum_reference_iterations = 262144 bailout.maximum_perturb_iterations = 4096 bailout.inscape_radius = 0.000976562 image.width = 601 image.height = 67 image.subframes = 64 transform.reflect = true transform.exponential_map = true render.zoom_out_sequence = true opencl.tile_width = 601 opencl.tile_height = 67 " channels (type chlist): B, 32-bit floating-point, sampling 1 1 G, 32-bit floating-point, sampling 1 1 R, 32-bit floating-point, sampling 1 1 compression (type compression): zip, multi-scanline blocks dataWindow (type box2i): (0 0) - (600 66) displayWindow (type box2i): (0 0) - (600 66) lineOrder (type lineOrder): increasing y pixelAspectRatio (type float): 1 screenWindowCenter (type v2f): (0 0) screenWindowWidth (type float): 1 type (type string): "scanlineimage"
- 现在已被完全自动的电影制作器 bash 脚本(存储库中的 kfbtoogv.sh)取代 - 只需指定长度(以秒为单位)和几个目录即可!有些事情是硬编码的(程序目录、抗锯齿因子、... - 需要将其设为运行时选项),而且使用 ghc 进行简单的数学运算有点过分,所以它还不是完美的。
- 我在一夜之间渲染了同一位置的 3840x2160 缩放出序列到 ~/work
- 然后我 mkdir ~/work/tmp,
- kfbtoogv.sh 120 ~/work ~/work/tmp 并且 18 分钟后获得了 此视频,无需手动操作
mkdir ~/work
cd ~/work
wine32 ~/windows/fraktal_sft.exe
# render zoom out sequence with kalles fraktaler, saving to ~/work
for i in *.kfb ; do ~/code/maximus_kf-extras/pseudo-de < ${i} | pgmtoppm white > ${i%kfb}ppm done
# count number of kfb files, (ls *.kfb | tail -n 1) gives a hint, I had 311
ls *.kfb | ~/code/maximus_kf-extras/expmap 311 > expmap.pgm
ghc -e "100 / sqrt ( 565 * 19820 / (120 * 8000) )"
# or your favourite calculator program if you don't have ghc
# prints 29.27922435677391
# where 565 * 19820 is the size of the expmap
# 8000 is desired sample rate
# 120 is desired movie length in seconds
gimp expmap.pgm
# downscale by 29.27922435677391% (output from ghci)
# flip vertically
# make sure it's greyscale with no alpha
# save as expmap-downscaled.png
# gimp saves comments in its netpbm writers, my bad code doesn't handle it
pngtopnm < expmap-downscaled.png > expmap-downscaled.pgm
audacity
# import raw expmap-downscaled.pgm as raw unsigned 8bit PCM mono 8000Hz
# set project sample rate to 48000Hz
# select the track, mix and render
# select the track, apply filter DC Offset Removal (maybe needs a plugin)
# select the track, select amplify and apply to normalize the volume
# duplicate the track twice
# for each of the duplicates in turn, select it and apply a reverb (GVerb plugin)
# use slightly different reverb settings for each track (for stereo effect)
# normalize the duplicates by select track, select amplify, apply
# make one duplicate a left channel and the other a right channel
# set the levels of each track to -3dB
# select all tracks, mix and render
# normalize volume if needed
# select track, export as stereo wav 16bit PCM to expmap.wav
# note down the length (my test gave 1m56s)
ghc -e "1 * 60 + 56"
# to get the audio length in seconds (116)
# check the size of the kfb files (here I used 640 by 360)
# remember we have 311 kfb files
ls 00*.ppm | tac | xargs cat | ~/code/maximus_book/code/zoom 640 360 311 116 |
avconv -f yuv4mpegpipe -i - -i expmap.wav -acodec vorbis -ab 192k -vb 2M out.ogv
# finally!
mplayer out.ogv
- 参数:http://mathr.co.uk/mandelbrot/2014-12-17_kf-extras_expmap_wire.kfr
- 从 98 个 640x360 kfb 文件渲染,生成一个 565x6075 的图像,在 GIMP 中缩小 4 倍以进行抗锯齿。[2]
"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.
- 平面图像 = 线性-线性比例图像(正常笛卡尔坐标)= 曼德勃罗集部分的标准平面视图。这里宽度和高度指的是平面图像。
- 对数极坐标图像(expmap)
- 圆周是输出条带的宽度
- 半径是每个部分的高度(为每个输入文件生成一个部分)
- expmap->row 变量是一个计数器,它遍历平面图像圆周中的同心圆,半径参数更复杂一些,这里有一段代码,它用了一些内联注释来实现:
- 指数映射 EXR 关键帧序列
- expmap
- 指数映射坐标变换(对于导出到 zoomasm 以进行高效的视频组装很有用)
- 围绕缩放中心的指数间隔环。见 图像 exponential_strip.svg