使用Lockbits实现Mandelbrot渲染器时渲染结果异常问题求助
问题排查与修复方案
- 遍历顺序错误:当前代码外层循环是x(列)、内层是y(行),但LockBits的内存排布是逐行存储的,应该把y循环放外层,x循环放内层,否则像素位置完全错位,是画面出现斜向断层的核心原因。
- 未处理行步长(Stride)对齐:24位RGB格式的位图每行末尾会自动填充字节,保证每行总字节数是4的倍数,你直接按像素数×3连续写数据,填充字节的位置会被你写入的像素数据占用,导致逐行偏移。
- 固定字节数硬编码不合理:你固定声明了2000000字节的数组、固定复制2000000字节,和实际位图所需的内存大小不匹配,一旦pictureBox尺寸变化就会出现内存越界或者数据不足的问题。
- 颜色通道顺序错误:Format24bppRgb的内存存储顺序是
B→G→R,你当前写入的顺序是G→B→R,会导致最终渲染颜色错乱。
修正后的代码如下:
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); // 按实际位图参数计算需要的字节数,不硬编码 int stride = bmpData.Stride; int bytesCount = stride * bmp.Height; byte[] bytes = new byte[bytesCount]; // 外层遍历行(y),内层遍历列(x),符合内存排布顺序 for (int y = 0; y < pictureBox1.Height; y++) { // 计算当前行的起始偏移,自动跳过行末尾的填充字节 int rowStart = y * stride; for (int x = 0; x < pictureBox1.Width; x++) { 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 bVal = (it % 128) * 2; // 计算当前像素的偏移位置 int pixelOffset = rowStart + x * 3; // 按B→G→R的顺序写入对应通道 bytes[pixelOffset] = (byte)bVal; bytes[pixelOffset + 1] = (byte)g; bytes[pixelOffset + 2] = (byte)r; } } System.Runtime.InteropServices.Marshal.Copy(bytes, 0, bmpData.Scan0, bytesCount); bmp.UnlockBits(bmpData); e.Graphics.DrawImage(bmp, 0, 0); bmp.Dispose();// 手动释放位图资源,避免内存泄漏 }
内容的提问来源于stack exchange,提问作者MultiThunderXXL
相关产品推荐
相关产品推荐

