Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitmap.Lockbits confusion

Tags:

c#

gdi+

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

From the link it says that the first argument will "specifies the portion of the Bitmap to lock" which I set to be a smaller part of the Bitmap (Bitmap is 500x500, my rectangle is (0,0,50,50)) however the returned BitmapData has stride of 1500 (=500*3) so basically every scan will still scan through the whole picture horizontally. However, what I want is only the top left 50x50 part of the bitmap.

How does this work out?

like image 525
Binh Tran Avatar asked May 27 '12 02:05

Binh Tran


1 Answers

The stride will always be of the full bitmap, but the Scan0 property will be different according to the start point of the lock rectangle, as well as the Height and Width of the BitmapData.

The reason for that is that you will still need to know the real bit-width of the bitmap, in order to iterate over the rows (add stride to address).

A simple way to go about it would be:

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

So it is basically really just locking the whole bitmap, but giving you a pointer to the top-left pixel of the rectangle in the bitmap, and setting the scan's width and height appropriately.

like image 166
SimpleVar Avatar answered Sep 24 '22 05:09

SimpleVar