一。代码
注:这里为了制造多个渲染效果使用委托类来当作函数指针使用。
private static Random rn = new Random();
private delegate UInt32 _dg_GetUint32Color(int i);
private const int mb_iteration = 24; //迭代次数限制
private static _dg_GetUint32Color[] _mbGetColors = new _dg_GetUint32Color[3];
//颜色迭代 委托
private static _dg_GetUint32Color mbGetColor = _mbGetColorA;
//三个颜色函数,直接影响渲染效果
private static UInt32 _mbGetColorA(int it)
{
UInt32 n = (UInt32)it * 8;
UInt32 r, g, b;
UInt32 old = n;
n = n % 255;
if (old < 255)
{
g = 255 - n;
b = n;
r = 0;
}
else
if (old < 255 * 2)
{
g = 0;
b = 255 - n;
r = n;
}
else
{
g = n;
b = 0;
r = 255 - n;
}
return 0xff000000+(r<<16)+(g<<8)+(b) ;
}
private static UInt32 _mbGetColorB(int it)
{
UInt32 n = (UInt32)it * 8;
UInt32 r, g, b;
UInt32 old = n;
n = n % 255;
if (old < 255)
{
b = 255 - n;
r = n;
g = 0;
}
else
if (old < 255 * 2)
{
b = 0;
r = 255 - n;
g = n;
}
else
{
b = n;
r = 0;
g = 255 - n;
}
return 0xff000000 + (r << 16) + (g << 8) + (b);
}
private static UInt32 _mbGetColorC(int it)
{
UInt32 n = (UInt32)it * 8;
UInt32 r, g, b;
UInt32 old = n;
n = n % 255;
if (old < 255)
{
r = 255 - n;
b = n;
g = 0;
}
else
if (old < 255 * 2)
{
r = 0;
b = 255 - n;
g = n;
}
else
{
r = n;
b = 0;
g = 255 - n;
}
return 0xff000000 + (r << 16) + (g << 8) + (b);
}
这是MandelBrot核心函数,如果固定公式的cc,再修改一下就是Julia分形。
/// <summary>
/// 迭代
/// </summary>
/// <param name="cc">复数</param>
/// <param name="n">阶数</param>
/// <returns>32bit颜色</returns>
private static UInt32 _mandelbrot(Complex cc, byte n)
{
Complex z = new Complex(0, 0);
for (int i = 0; i < mb_iteration; i++)
{
// if (z.square > 4) return _mbGetColorB(i);
if (z.square > 4) return mbGetColor((int)(z.real) * (10 - n));
z = Complex.pow(z, n) + cc;
}
return 0xFF000000;//背景色
}
如果直接操作gs进行一点一点地绘图,也行,但是慢,所以这里直接使用指针(虽然C#不推荐使用指针)。 其实运行程序的时间基本耗在上面的迭代函数,与绘图方式关系不大。(单纯的绘图,使用指针比使用gs画点快几十倍!)
/// <summary>
/// 分形Mandelbrot
/// </summary>
/// <param name="gs">画面</param>
/// <param name="s">面积</param>
/// <param name="n">阶数</param>
unsafe public static void DrawMandelbrot(Graphics gs, Size s, byte n)
{
_mbGetColors[0] = _mbGetColorA;
_mbGetColors[1] = _mbGetColorB;
_mbGetColors[2] = _mbGetColorC;
mbGetColor = _mbGetColors[rn.Next(3)];
double par = 1;//系数
double offsetx=0, offsety=0;//偏移
Bitmap srcbmp = new Bitmap(s.Width ,s.Height);
BitmapData bmpData = srcbmp.LockBits(new Rectangle(0, 0, srcbmp.Width, srcbmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
UInt32 stride = (UInt32)bmpData.Stride;
byte* srcbuf = (byte*)bmpData.Scan0.ToPointer();
double xx=0, yy=0;
Complex cc = new Complex(0,0);
for (UInt32 j = 0; j < s.Height; j++)
{
yy = ((double)j / s.Width) * 4 * (par) - 2 * (par);
for (UInt32 i = 0; i < s.Width; i++)
{
xx = ((double)i / s.Height) * 4 * (par) - 2 * (par);
cc = new Complex(xx + offsetx, yy + offsety);
UInt32* ptr = (UInt32*)(srcbuf + i * 4 + j * stride);
*ptr = _mandelbrot(cc, n);
}
}
srcbmp.UnlockBits(bmpData);
gs.DrawImage(srcbmp,0,0);
srcbmp.Dispose();
}
二。效果图
MandelBrot分形:二阶图像,渲染的颜色单调
调整渲染参数:
多阶图像
再试试Julia分形