Bitmap.Lockbits混淆

Bin*_*ran 7 c# gdi+

MSDN参考:[1] http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx#Y1178

从链接中它说第一个参数将"指定要锁定的位图部分",我将其设置为位图的较小部分(位图为500x500,我的矩形为(0,0,50,50))但是返回的BitmapData的步幅为1500(= 500*3),因此基本上每次扫描都会水平扫描整个图像.但是,我想要的只是位图的左上角50x50部分.

这是如何解决的?

Sim*_*Var 10

步幅将始终为完整位图,但Scan0属性将根据锁定矩形的起点以及BitmapData的高度和宽度而不同.

原因是你仍然需要知道位图的实际位宽,以便遍历行(添加步幅到地址).

一个简单的方法是:

var bitmap = new Bitmap(100, 100);

var data = bitmap.LockBits(new Rectangle(0, 0, 10, 10),
                           ImageLockMode.ReadWrite,
                           bitmap.PixelFormat);

var pt = (byte*)data.Scan0;
var bpp = data.Stride / bitmap.Width;

for (var y = 0; y < data.Height; y++)
{
    // This is why real scan-width is important to have!
    var row = pt + (y * data.Stride);

    for (var x = 0; x < data.Width; x++)
    {
        var pixel = row + x * bpp;

        for (var bit = 0; bit < bpp; bit++)
        {
            var pixelComponent = pixel[bit];
        }
    }
}

bitmap.UnlockBits(data);
Run Code Online (Sandbox Code Playgroud)

所以它基本上只是锁定整个位图,但是给你一个指向位图中矩形左上角像素的指针,并适当地设置扫描的宽度和高度.

  • 无法保证位图的步幅等于(每个像素的宽度*字节数),因此"var bpp = data.Stride/bitmap.Width;" 是错误的(您可以轻松地创建具有不同步幅的位图).你可以使用(((bitmap.Pixelformat)>> 8)&255)来获得每个像素的位数,或者(((bitmap.Pixelformat)>> 11)&31)每个像素的字节数. (3认同)
  • 仅供参考,这里有`GetPixelFormatSize`,http://msdn.microsoft.com/en-us/library/system.drawing.image.getpixelformatsize (2认同)