Reading a Bitmap in Unsafe vs InteropServices.Marshall
-
Hi, I've got the following code which reads from an image that has information encoded in as pixels. My job is to scan through the image, and set the value of an array to true if a pixel is black, and false if it is any other color. I have the following bit of unsafe code that performs it:
BitmapData bmpdata = AOIImg.LockBits(new Rectangle(0, 0, WIDTH, HEIGHT), ImageLockMode.ReadOnly, AOIImg.PixelFormat); IntPtr scan0 = bmpdata.Scan0; int stride = bmpdata.Stride; int imgOffs; try { //loop through the image and set the main AOI mask unsafe { byte* imgPtr; for (int y = 0; y < HEIGHT; ++y) { imgOffs = y * stride; imgPtr = &((byte*)scan0)[imgOffs]; for (int x = 0; x < WIDTH; ++x) { //checks the blue, green, and red values of the pixel to see if it's black if (imgPtr[0] == 0 && imgPtr[1] == 0 && imgPtr[2] == 0) { //pixel is black -- exclude from aoi mask AOIMask[y * WIDTH + x] = true; } else //no feature { AOIMask[y * WIDTH + x] = false; } imgPtr += 3; //advance ptr by 3 bytes (one pixel) } } } } finally { AOIImg.UnlockBits(bmpdata); #if DEBUG //TODO -- remove AOIImg.Save(@"C:\temp.png", ImageFormat.Png); #endif AOIImg.Dispose(); }
However, I was wondering if I could turn this into managed code using InteropsServices.Marshall to copy the pixel data to an array and read through it in a safe context. I was wondering if anyone had any warnings about using this method, such as the stride not being correctly accounted for in the marshalled array (I'm not sure if I have to do this manually or not at all!). Thanks in advance, Phil
-
Hi, I've got the following code which reads from an image that has information encoded in as pixels. My job is to scan through the image, and set the value of an array to true if a pixel is black, and false if it is any other color. I have the following bit of unsafe code that performs it:
BitmapData bmpdata = AOIImg.LockBits(new Rectangle(0, 0, WIDTH, HEIGHT), ImageLockMode.ReadOnly, AOIImg.PixelFormat); IntPtr scan0 = bmpdata.Scan0; int stride = bmpdata.Stride; int imgOffs; try { //loop through the image and set the main AOI mask unsafe { byte* imgPtr; for (int y = 0; y < HEIGHT; ++y) { imgOffs = y * stride; imgPtr = &((byte*)scan0)[imgOffs]; for (int x = 0; x < WIDTH; ++x) { //checks the blue, green, and red values of the pixel to see if it's black if (imgPtr[0] == 0 && imgPtr[1] == 0 && imgPtr[2] == 0) { //pixel is black -- exclude from aoi mask AOIMask[y * WIDTH + x] = true; } else //no feature { AOIMask[y * WIDTH + x] = false; } imgPtr += 3; //advance ptr by 3 bytes (one pixel) } } } } finally { AOIImg.UnlockBits(bmpdata); #if DEBUG //TODO -- remove AOIImg.Save(@"C:\temp.png", ImageFormat.Png); #endif AOIImg.Dispose(); }
However, I was wondering if I could turn this into managed code using InteropsServices.Marshall to copy the pixel data to an array and read through it in a safe context. I was wondering if anyone had any warnings about using this method, such as the stride not being correctly accounted for in the marshalled array (I'm not sure if I have to do this manually or not at all!). Thanks in advance, Phil
You'll have to account for stride manually, but there is nothing to this. The Marshal.Copy() method just copy blocks of data. If Stride and (Width * BytesPerPixel) are not equal, then the data at the end of each image row is padded with zeros. This doesn't matter. Make sure you allocate a byte [] array of size = height * stride, and use marshal.copy to fill it. Use nested loops to avoid any stride difference:-
for (y=0; y
using System.Beer;
-
You'll have to account for stride manually, but there is nothing to this. The Marshal.Copy() method just copy blocks of data. If Stride and (Width * BytesPerPixel) are not equal, then the data at the end of each image row is padded with zeros. This doesn't matter. Make sure you allocate a byte [] array of size = height * stride, and use marshal.copy to fill it. Use nested loops to avoid any stride difference:-
for (y=0; y
using System.Beer;
Thanks, This will be double the memory usage of the unsafe version, correct? -Phil
-
Thanks, This will be double the memory usage of the unsafe version, correct? -Phil
Sure, twice the memory, and a lot slower if you dont use a pointer... :)
Luc Pattyn [My Articles] [Forum Guidelines]