Speed. Copy bitmap data into array or work with it directly?
I am using a class LockedBitmap
that makes it easy to work with raster data in C #. It is currently copying data into a local array byte[]
, which then accesses its class methods to get / set pixel color values.
Is this faster or better than accessing the locked bitmap data directly via a pointer? Is a copy required?
Edit: I am not asking if its possible to work with raster data directly, I work with this every day. I'm just asking for a comparison between the two methods and, if necessary, for copying pixel data.
Copying pixel data to 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);
Direct reading of 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 a pointer?
Not. This requires an additional copy operation and then another operation to copy the processed values back to the bitmap.
Is a copy required?
Only in an environment where code is unsafe
not desired or available.
You can definitely work directly on the bitmap data without copying it. Here is some code I used to pull the 16bpp client gray-box format into the rendered 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);
Key LockBits
andUnlockBits
As a quick explanation, I am reading 16bpp from file in bytes
, restoring 16 bits in value
. Then, using external settings iMin
and iMax
to get the correct shading. Then take this single one value
and plot it RGB and use Marshal.Copy
to place it in a bitmap.