我正在尝试将Mandelbrot设置为彩色并使其看起来不错。我想复制image from the Wikipedia page。 Wikipedia图像还包括Ultra Fractal 3参数文件。
import pandas as pd
import xml.etree.ElementTree as ET
import os
from collections import defaultdict, OrderedDict
tree = ET.parse('PowerChange_76.xml')
root = tree.getroot()
df_list = []
for i, child in enumerate(root):
for subchildren in child.findall('{raml20.xsd}header'):
for subchildren in child.findall('{raml20.xsd}managedObject'):
match_found = 0
xml_class_name = subchildren.get('class')
xml_dist_name = subchildren.get('distName')
print(xml_class_name)
df_dict = OrderedDict()
for subchild in subchildren:
header = subchild.attrib.get('name')
df_dict['Class'] = xml_class_name
df_dict['CellDN'] = xml_dist_name
df_dict[header]=subchild.text
df_list.append(df_dict)
df_cm = pd.DataFrame(df_list)
我一直试图解密该文件,并编写一个程序来重现Wikipedia图像。这是我的最佳尝试:
这是渲染器的一部分。这有点混乱,因为我在摆弄并重写大量的块,试图弄清楚这个问题。
mandelZoom00MandelbrotSet {
fractal:
title="mandel zoom 00 mandelbrot set" width=2560 height=1920 layers=1
credits="WolfgangBeyer;8/21/2005"
layer:
method=multipass caption="Background" opacity=100
mapping:
center=-0.7/0 magn=1.3
formula:
maxiter=50000 filename="Standard.ufm" entry="Mandelbrot" p_start=0/0
p_power=2/0 p_bailout=10000
inside:
transfer=none
outside:
density=0.42 transfer=log filename="Standard.ucl" entry="Smooth"
p_power=2/0 p_bailout=128.0
gradient:
smooth=yes rotation=29 index=28 color=6555392 index=92 color=13331232
index=196 color=16777197 index=285 color=43775 index=371 color=3146289
opacity:
smooth=no index=0 opacity=255
}
using real = double;
using integer = long long;
struct complex {
real r, i;
};
using grey = unsigned char;
struct color {
grey r, g, b;
};
struct real_color {
real r, g, b;
};
grey real_to_grey(real r) {
// converting to srgb didn't help much
return std::min(std::max(std::round(r), real(0.0)), real(255.0));
}
color real_to_grey(real_color c) {
return {real_to_grey(c.r), real_to_grey(c.g), real_to_grey(c.b)};
}
real lerp(real a, real b, real t) {
return std::min(std::max(t * (b - a) + a, real(0.0)), real(255.0));
}
real_color lerp(real_color a, real_color b, real t) {
return {lerp(a.r, b.r, t), lerp(a.g, b.g, t), lerp(a.b, b.b, t)};
}
complex plus(complex a, complex b) {
return {a.r + b.r, a.i + b.i};
}
complex square(complex n) {
return {n.r*n.r - n.i*n.i, real{2.0} * n.r * n.i};
}
complex next(complex z, complex c) {
return plus(square(z), c);
}
real magnitude2(complex n) {
return n.r*n.r + n.i*n.i;
}
real magnitude(complex n) {
return std::sqrt(magnitude2(n));
}
color lerp(real_color a, real_color b, real t) {
return real_to_grey(lerp(a, b, t));
}
struct result {
complex zn;
integer n;
};
result mandelbrot(complex c, integer iterations, real bailout) {
complex z = {real{0.0}, real{0.0}};
integer n = 0;
real bailout2 = bailout * bailout;
for (; n < iterations && magnitude2(z) <= bailout2; ++n) {
z = next(z, c);
}
return {z, n};
}
struct table_row {
real index;
real_color color;
};
real invlerp(real value, real min, real max) {
return (value - min) / (max - min);
}
color lerp(table_row a, table_row b, real index) {
return lerp(a.color, b.color, invlerp(index, a.index, b.index));
}
color mandelbrot_color(complex c, integer iterations, real bailout) {
const result res = mandelbrot(c, iterations, bailout);
if (res.n == iterations) {
// in the set
return {0, 0, 0};
} else {
table_row table[] = {
// colors and indicies from gradient section
{28.0*0.1, {0x00, 0x07, 0x64}},
{92.0*0.1, {0x20, 0x6B, 0xCB}},
{196.0*0.1, {0xED, 0xFF, 0xFF}},
{285.0*0.1, {0xFF, 0xAA, 0x00}},
{371.0*0.1, {0x31, 0x02, 0x30}},
// interpolate towards black as we approach points that are in the set
{real(iterations), {0, 0, 0}}
};
// it should be smooth, but it's not
const real smooth = res.n + real{1.0} - std::log(std::log2(magnitude(res.zn)));
// I know what a for-loop is, I promise
if (smooth < table[1].index) {
return lerp(table[0], table[1], smooth);
} else if (table[1].index <= smooth && smooth < table[2].index) {
return lerp(table[1], table[2], smooth);
} else if (table[2].index <= smooth && smooth < table[3].index) {
return lerp(table[2], table[3], smooth);
} else if (table[3].index <= smooth && smooth < table[4].index) {
return lerp(table[3], table[4], smooth);
} else {
return lerp(table[4], table[5], smooth);
}
}
}
部分中的颜色在gradient
中的表中。 mandelbrot_color
部分的索引也在表中,但我将它们乘以gradient
。如果我不乘以0.1
,颜色就会完全消失。
0.1
部分包含formula
和maxiter=50000
。它们是代码中的p_bailout=10000
和iterations
。我不知道bailout
是什么意思。我不知道为什么在p_start=0/0 p_power=2/0
部分中提到了不同的纾困方案,而且我也不知道outside
,density=0.42
,transfer=none
的含义。 transfer=log
部分还提到了gradient
,但我不知道如何旋转渐变。
我问这个问题的原因是,我不喜欢图像周围的白色条纹(我更希望像Wikipedia图像中那样平滑而发光)。我也不喜欢由向黑色插值(rotation=29
表中的最后一行)而导致的深紫色皮肤。如果删除该行,则最终将显示深蓝色的皮肤。
我怀疑从mandelbrot_color
部分的索引到迭代计数有某种映射。也许gradient
是该映射的近似值,该映射有时会起作用。可能与* 0.1
,transfer
或density
有关。如果您希望我发布整个程序,请发表评论。它取决于rotation
(单个标头图像编写库)。
作为旁注,我已经清理了这段代码并将其放入片段着色器中,它(通常来说)可能比在CPU上运行多线程更快吗?