我正在尝试为我的Mandelbrot渲染器实现Lockbits,因为它的性能更好。然而,在尝试呈现mandelbrot函数时,我似乎得到了一个非常有趣的结果。我所做的基本上是获取每个像素的RGB值,然后将它们放入字节数组中。之后,我将它们全部复制到位图中并绘制它们。
渲染器的代码:
private void Draw(object sender, PaintEventArgs e)
{
Bitmap bmp = new Bitmap(pictureBox1.Width, pictureBox1.Height);
double minX = centerX - zoom / 2, minY = centerY - zoom / 2;
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
IntPtr ptr = bmpData.Scan0;
int ret = 0;
byte[] bytes = new byte[2000000];
for (int x = 0; x < pictureBox1.Width; x++)
{
for (int y = 0; y < pictureBox1.Height; y++)
{
double a = minX + (double)x / pictureBox1.Width * zoom;
double b = minY + (double)y / pictureBox1.Height * zoom;
Complex c = new Complex(a, b);
Complex z = new Complex(0, 0);
int it = 0;
do
{
it++;
z.Square();
z.Add(c);
if (z.Magnitude() > 2.0)
{
break;
}
}
while (it < 50);
int r = (it % 32) * 7;
int g = (it % 16) * 14;
int b = (it % 128) * 2;
int l = 255;
if (ret <= 1999997)
{
bytes[ret] = (byte)g;
bytes[ret + 1] = (byte)b;
bytes[ret + 2] = (byte)r;
ret = ret + 3;
}
}
}
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, ptr, 2000000);
bmp.UnlockBits(bmpData);
e.Graphics.DrawImage(bmp, 0, 0);
}结果:

发布于 2021-09-02 18:51:32
这里有几个地方出了问题。为了使示例工作,我在方法中声明了一些变量。下一次,请提供一个可重现的例子,这样人们就不需要那么多的摆弄了。
我还将Complex类型更改为System.Numerics.Complex,因为您没有提到正在使用哪个库。
位图bmp =新位图(pictureBox1.Width,pictureBox1.Height,PixelFormat.Format24bppRgb);
b声明了两次,因此代码无法编译。我将后一个更改为blue.这意味着:在每一行之后,必须将差值添加到ret变量中:
ret = ret + bmpData.Stride - pictureBox1.Width * 3;
for (int y= 0;y< pictureBox1.Height;y++) { for (int x= 0;x< pictureBox1.Width;x++) {
通过分配您所需大小的byte[]来修复此问题。
byte[]字节=新的bytebmp.Height * bmpData.Stride;
然后更改所有边界检查。
字节数=(字节)蓝色;字节数+1=(字节)g;字节数+2=(字节)r;
我不想发布完整的代码,因为我认为你犯了很多错误,应该自己修复它们。复制/粘贴不利于学习。但是,以下是使用参数运行时修复的结果
var zoom = 2.0;
var centerX = -.2;
var centerY = 0.0;

你会注意到,如果图像不是方形的,它看起来会被拉伸。您可能希望在计算中对此进行补偿。
另外:当前在Paint事件中绘制图像。你的窗口可能比你想象的要频繁的多。也许你会找到一个更好的地方。
在我的机器上,2560x1440像素的全屏更新需要大约2100ms。它可能仍然需要更多的性能:-)如果你避免使用ret,而是用一个计算来代替它,那么在外部y循环上使用Parallel.For()是可能的。这样我就可以在300ms (8个内核;16个线程)下运行。
https://stackoverflow.com/questions/69034592
复制相似问题