6

我想我找到了一种更快的方法来在 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两个位图的s不同,这种方法可能不会总是正确复制。但是,由于LockBits需要指定像素格式,因此似乎已处理。(如果是这样,那么在另外 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);
    }
4

1 回答 1

3

改为使用Bitmap.Clone()。GDI+ 往往不报告异常,由此产生的错误将很难跟踪。

将图像复制到位图中的一种非常快速的方法是Graphics.DrawImage() 只要您不转换像素格式或缩放图像

于 2013-06-25T16:52:10.007 回答