Nic*_*son 30 algorithm colors fractals mandelbrot
我目前正在编写一个程序来生成真正巨大的(65536x65536像素及以上)Mandelbrot图像,我想设计一种能够正义的光谱和着色方案.在维基百科特色的Mandelbrot图像似乎是一个很好的例子,调色板尤其是如何保持在序列中的所有缩放级别变化.不过,我不确定它是在旋转调色板还是做其他一些技巧来实现这一点.
我熟悉mandelbrot集的平滑着色算法,所以我可以避免使用条带,但我仍然需要一种方法来为此算法的输出值指定颜色.
我正在生成的图像是金字塔形的(例如,一系列图像,每个图像的尺寸都是前一个图像的一半),所以我可以使用某种旋转调色板,只要调色板之间的变化即可缩放级别不是太明显.
Per*_*son 32
这是平滑的颜色算法:
让我们说你从复数开始,z0
迭代n
次数直到它逃脱.让终点是zn
.
一个平滑的价值
nsmooth := n + 1 - Math.log(Math.log(zn.abs()))/Math.log(2)
Run Code Online (Sandbox Code Playgroud)
这仅适用于mandelbrot,如果你想为julia集计算平滑函数,那么使用
Complex z = new Complex(x,y);
double smoothcolor = Math.exp(-z.abs());
for(i=0;i<max_iter && z.abs() < 30;i++) {
z = f(z);
smoothcolor += Math.exp(-z.abs());
}
Run Code Online (Sandbox Code Playgroud)
然后smoothcolor
是在间隔(0,max_iter)
.
分smoothcolor
与max_iter
得到0和1之间的一个数值.
要从值中获得平滑的颜色:
这可以被调用,例如(在Java中):
Color.HSBtoRGB(0.95f + 10 * smoothcolor ,0.6f,1.0f);
Run Code Online (Sandbox Code Playgroud)
因为HSB颜色参数中的第一个值用于定义色环的颜色.
使用平滑着色算法计算视口中的所有值,然后将调色板从最低值映射到最高值.因此,当您放大并且较高的值不再可见时,调色板也会缩小.对于n和B使用相同的常量,对于完全缩小的集合,最终会得到0.0到1.0的范围,但是在更深的缩放处,动态范围将缩小,例如在200%缩放时为0.0到0.1,0.0到0.0001 at 20000%变焦等
小智 5
这是一个天真的Mandelbrot发电机的典型内环.要获得平滑的颜色,您需要传递真实和复杂的"长度"以及您提供的迭代.我已经包含了Mandelbrot代码,因此您可以查看用于计算颜色的变量.
for (ix = 0; ix < panelMain.Width; ix++)
{
cx = cxMin + (double )ix * pixelWidth;
// init this go
zx = 0.0;
zy = 0.0;
zx2 = 0.0;
zy2 = 0.0;
for (i = 0; i < iterationMax && ((zx2 + zy2) < er2); i++)
{
zy = zx * zy * 2.0 + cy;
zx = zx2 - zy2 + cx;
zx2 = zx * zx;
zy2 = zy * zy;
}
if (i == iterationMax)
{
// interior, part of set, black
// set colour to black
g.FillRectangle(sbBlack, ix, iy, 1, 1);
}
else
{
// outside, set colour proportional to time/distance it took to converge
// set colour not black
SolidBrush sbNeato = new SolidBrush(MapColor(i, zx2, zy2));
g.FillRectangle(sbNeato, ix, iy, 1, 1);
}
Run Code Online (Sandbox Code Playgroud)
和MapColor如下:(请参阅此链接以获取ColorFromHSV函数)
private Color MapColor(int i, double r, double c)
{
double di=(double )i;
double zn;
double hue;
zn = Math.Sqrt(r + c);
hue = di + 1.0 - Math.Log(Math.Log(Math.Abs(zn))) / Math.Log(2.0); // 2 is escape radius
hue = 0.95 + 20.0 * hue; // adjust to make it prettier
// the hsv function expects values from 0 to 360
while (hue > 360.0)
hue -= 360.0;
while (hue < 0.0)
hue += 360.0;
return ColorFromHSV(hue, 0.8, 1.0);
}
Run Code Online (Sandbox Code Playgroud)
MapColour正在"平滑"从0到1的救助值,然后可以用来映射颜色而不会出现可怕的条带.使用MapColour和/或hsv函数可以改变使用的颜色.
我最终的解决方案是创建一个美观(且相当大)的调色板,并将其作为常量数组存储在源中,然后使用平滑着色算法在其中的索引之间进行插值。调色板环绕(并且设计为连续的),但这似乎并不重要。