Reputation: 113976
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];
Upvotes: 3
Views: 7260
Reputation: 21917
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.
Upvotes: 3
Reputation: 2256
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.
Upvotes: 2