我认为我发现了一种更快捷的方法来复制c#中的位图。 (如果它有效,我确定我不是第一个,但我还没有看到它。)
我能想到的最简单的方法就是断言我的想法是基于什么,如果没有人在其中发现漏洞,假设这个想法是合理的:
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
只是将位图中的像素数据块复制到固定内存中,然后使用UnlockBits
2)使用LockBits
不会影响复制的内存块,因此它对从中复制的图像没有影响。
3)由于您从未输入unsafe
代码,因此不存在破坏内存的风险。
我看到可能的漏洞:
1)如果两个位图的PixelFormat
不同,则此方法可能无法始终正确复制。但是,由于LockBits
需要指定pixelformat,所以似乎可以处理。 (如果是这样的话,对于那个开销而言,其他99.9%的时间我们没有切换像素格式!/ EndSarcasm)
2)如果两个位图的步幅不匹配,则可能存在问题(因为stride
是复制操作中外部for循环的递增器。)此问题会限制复制到位图等于步幅。
编辑:我认为断言#2一定是错的......我在尝试稍后访问通过CopyMe传递的位图时发现了一个错误。下面的解决方法,但我不确定它是否留下了一块固定内存。 (内存泄漏警报!)
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);
}
答案 0 :(得分:3)
请改用Bitmap.Clone()
。 GDI +往往不会报告异常,因此很难跟踪产生的错误。
将图像复制到位图的非常快速方式是使用Graphics.DrawImage()
,只要您不转换像素格式或缩放图像。 / p>