I think I've found a MUCH faster way to copy bitmaps in c#. (If it's valid, I'm sure I wasn't the first but I haven't seen it anywhere yet.)
The simplest way I can think to ask this is to assert what I based my idea on and if no one shoots holes in it, assume the idea is sound:
void FastCopyRegion(Bitmap CopyMe, ref Bitmap IntoMe, Rectangle CopyArea)
{
//`IntoMe` need not be declared `ref` but it brings
// attention to the fact it will be modified
Debug.Assert(CopyMe.PixelFormat == IntoMe.PixelFormat,
"PixelFormat mismatch, we could have a problem");
Debug.Assert(CopyMe.Width == IntoMe.Width, //This check does not verify
"Stride mismatch, we could have a problem");// sign of `stride` match
BitmapData copyData = CopyMe.LockBits(CopyArea,
ImageLockMode.ReadWrite, CopyMe.PixelFormat);
IntoMe.UnlockBits(copyData);
}
1) LockBits
simply copies a block of pixel data out of a bitmap to fixed memory to be edited and copied back in using UnlockBits
2) Using LockBits
does not affect the copied memory block so it should have no effect on the image copied from.
3) Since you never enter unsafe
code, there should be no risk of corrupting memory.
Possible holes I see:
1) If the PixelFormat
s of the two bitmaps are different, this method may not always copy correctly. However, since LockBits
requires specifying a pixelformat, it seems this is handled. (If so, hooray for that overhead the other 99.9% of the time we're not switching pixelformats! /EndSarcasm)
2) If the stride of the two bitmaps doesn't match, there could be a problem (because stride
is the outer for loop's incrementor in the copy operation.) This problem would limit copying to bitmaps with equal stride.
Edit: I think assertion #2 must be wrong... I just found an error when trying to later access the bitmap passed through CopyMe. Workaround below, but I'm not sure if it leaves a block of fixed memory lying around. (memory leak alert!)
void FastCopyRegion(Bitmap CopyMe, ref Bitmap IntoMe, Rectangle CopyArea)
{
//`IntoMe` need not be declared `ref` but it brings attention to the fact it will be modified
Debug.Assert(CopyMe.PixelFormat == IntoMe.PixelFormat, "PixelFormat mismatch, we could have a problem");
Debug.Assert(CopyMe.Width == IntoMe.Width, "Width mismatch, we could have a problem");
BitmapData copyD = IntoMe.LockBits(CopyArea, ImageLockMode.ReadWrite, CopyMe.PixelFormat);
BitmapData copyData = CopyMe.LockBits(CopyArea, ImageLockMode.ReadWrite, CopyMe.PixelFormat);
CopyMe.UnlockBits(copyData);
IntoMe.UnlockBits(copyData);
}
LockBits
, you'd follow it withunsafe
code to directly access memory. I'm usingLockBits
and not doingunsafe
code. – EdomiteGraphics.DrawImage()
– Edomite