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

C#中Bitmap类是否在内部按列存储像素?附MSDN代码示例

C# Bitmap类内部是按列存储像素吗?

嘿,这个问题问得很关键!答案是:C#的Bitmap类内部并非按列存储像素,而是采用行优先(Row-major)的存储方式——也就是先完整存储第一行的所有像素,再存储第二行,以此类推,逐行往下。

为什么这么说?

Bitmap类底层依赖GDI+的位图实现,而GDI+的位图结构天生就是行优先的。每一行的像素数据会连续存放在内存中,不过为了满足内存对齐要求,每行末尾可能会添加一些填充字节(这就是Stride属性的由来,它代表每行实际占用的字节数,可能比宽度×每个像素字节数要大)。

结合你给出的MSDN代码示例来看

你贴的这段代码:

private void SetPixel_Example(PaintEventArgs e) {
    // Create a Bitmap object from a file.
    Bitmap myBitmap = new Bitmap("Grapes.jpg");
    // Draw myBitmap to the screen.
    e.Graphics.DrawImage(myBitmap, 0, 0, myBitmap.Width, myBitmap.Height);
    // Set each pixel in myBitmap to black.
    for (int Xcount = 0; Xcount < myBitmap.Width; Xcount++) {
        for (int Ycount = 0; Ycount < myBitmap.Height; Ycount++) {
            myBitmap.SetPixel(Xcount, Ycount, Color.Black);
        }
    }
    //...
}

这里的循环是先遍历X(列方向)再遍历Y(行方向),其实这种方式的效率并不高——因为每次Y变化时,都要跳转到下一行的内存起始位置,而X在每行内来回跳转,缓存命中率低。如果改成先遍历Y(行)再遍历X(列),内存访问会更连续,速度会快很多,这也从侧面印证了Bitmap是行优先存储的。

高效操作像素的方式

如果要批量处理像素,推荐使用LockBits方法直接访问内存缓冲区,这时候能更直观看到行优先的结构:

  • Scan0属性指向第一行第一个像素的内存地址
  • Stride是每行的总字节数(含填充)
  • 第Y行第X列的像素起始地址 = Scan0 + Y * Stride + X * 每个像素的字节数

内容的提问来源于stack exchange,提问作者John Z. Li

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:00:25