2012-05-27 110 views
7

MSDN參考:[1] http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx#Y1178Bitmap.Lockbits混亂

從鏈接它說,第一個參數將「指定位圖的該部分以鎖定」,我設置爲位圖的一小部分(位圖是500x500,我的矩形是(0,0,50,50)),但返回的BitmapData跨度爲1500(= 500 * 3),因此基本上每次掃描都會水平掃描整個圖片。但是,我想要的只是位圖左上角的50x50部分。

這是如何工作的?

回答

9

步幅將始終爲完整位圖,但根據鎖定矩形的起點以及BitmapData的高度和寬度,Scan0屬性將會不同。

原因是,您仍然需要知道位圖的實際位寬,以遍歷行(添加步長到地址)。

一個簡單的方法去了解這將是:

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); 

所以它基本上是真的只是鎖定整個位圖,但給你一個指針到矩形的左上角的像素的位圖,並適當設置掃描的寬度和高度。

+0

謝謝。這就說得通了! –

+3

無法保證位圖的步幅將等於(每個像素的寬度*字節數),因此「var bpp = data.Stride/bitmap.Width;」是錯誤的(你可以輕鬆地創建一個不同的步幅位圖)。您可以使用((((bitmap.Pixelformat)>> 8)&255)來獲取每像素的位數,或((((bitmap.Pixelformat)>> 11)&31)。 –

+0

另外,如果步幅對您很重要,您可以使用ImageLockMode.UserInputBuffer提供自己的緩衝區和步幅。 –