I'm using a LockedBitmap class that simplifies working with bitmap data in C#. Currently it is copying the data into a local byte[] array which is then accessed by its class methods to get/set pixel color values.
Is this faster or better than accessing the locked bitmap data directly via the pointer? Is a copy needed at all?
Edit: I'm not asking if its possible to directly work with bitmap data, I work with this everyday. I'm just asking for a comparison between the 2 methods and if its necessary at all to copy pixel data.
Copying pixel data into a temp array:
// create byte array to copy pixel values
int step = Depth / 8;
Pixels = new byte[PixelCount * step];
Iptr = bitmapData.Scan0;
// Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
Directly reading pixel values:
byte* p = (byte*)(void*)bmData.Scan0.ToPointer();
int ws = bmData.Stride;
byte* row = &p[i * ws];
byte Gcolor = row[j];
byte Bcolor = row[j + 1];
byte Rcolor = row[j + 2];
Is this faster or better than accessing the locked bitmap data directly via the pointer?
No. It requires an additional copy operation, and then another operation to copy the processed values back to the bitmap.
Is a copy needed at all?
Only in an environment where unsafe code is undesired or unavailable.
You can definitely operate directly on the bitmap data without copying it. Here is some code that I used to pull in a customer 16bpp gray scale format into a displayable bitmap:
Rectangle rect = new Rectangle(0, 0, bmOut.Width, bmOut.Height);
System.Drawing.Imaging.BitmapData bmpData =
bmOut.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
bmOut.PixelFormat);
IntPtr ptr = bmpData.Scan0;
Byte[] bytes;
bytes = rawIn.ReadBytes(framesize);
for (int x = 0; x < bytes.Length; x += 2)
{
short[] rgb = new short[3];
int value = bytes[x + 1] * 256 + bytes[x];
//value = value / 32;
value = iMax * (value - iMin) / (iMax - iMin);
if (value < iMin)
{
value = iMin;
}
else if (value > iMax)
{
value = iMax;
}
value = 65536 * (value - iMin) / (iMax - iMin);
rgb[0] = rgb[1] = rgb[2] = (short)(value);
System.Runtime.InteropServices.Marshal.Copy(rgb, 0, ptr + (x) * 3, 3);
}
bmOut.UnlockBits(bmpData);
The key is the LockBits and UnlockBits
As a quick explanation, I'm reading 16bpp from the file into bytes, reconstructing the 16 bits into value. Then, using externally supplied iMin and iMax scaling to get the shading right. Then taking that single value and constructing the RGB and using the Marshal.Copy to put it into the bitmap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With