views:

256

answers:

1

This may be a repeat of the following unanswered question:

 Help with bitmap lock - Format8bppIndexed

I'm locking an image in the following manner:

// PixelFormat is 8BppIndexed in my case.
Bitmap bmp = new Bitmap("mySampleImage.tif");

// ClipRectangle will be a Rectangle such as {x=128, y=290, width=250, height=200},
// selected by the user by seeing the image on screen. Thus, it's a valid region
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

unsafe
{
  byte* origin = (byte*)data.Scan0.ToPointer();

  // Processing...
}

In the processing section, I step through the pixels in the ClipRectangle in the Y direction. However, a pixel that should be valid returns with a memory access error, saying I cannot dereference the pointer.

For example, in a 704x600 image using:

ClipRectangle = {x=128, y=290, width=250, height=200}
The pixel `(128x321)` should be valid. By manually typing in the math to get that pixel in the intermediate window, I get the following:
origin + (321 * stride) + 128
0x053a80c0
    *(origin + (321 * stride) + 128): Cannot dereference 'origin + (321 * stride) + 128'. The pointer is not valid.

Stride is 704, the logic in my software comes up with the exact pointer location as the intermediate window, so everything seems right. The Y pixels from 290-320 can be dereferenced just fine. If I instead lock the entire Bitmap, all my logic proceeds fine, but I have doubts about whether I'm getting the right pixels, or how the locking rectangle is used in LockBits.

Why can I not access the expected locked pixels in the BitmapData when I lock only the region I need?

+3  A: 

When you lock bits using a rectangle with an offset, BitmapData.Scan0 doesn't return the bitmap origin, but rather the specified rectangle origin.

So, if you used:

Rectangle rect = new Rectangle(128, 290, 250, 200);
BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

then the maximum offset from Scan0 is (250 * Stride) + 200.

In other words, the pixel at (128x321) would be at (Scan0 + (321 - 290) * Stride).

Groo
I thought this might be the case, and scoured MSDN for a word about this before posting, but never found it. Thanks.
Will Eddins