You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:00:05