以这种方式使用锁定位来复制位图区域是否安全(双关语)?

App*_*Fzx 6 c# copy bitmap lockbits

我想我已经找到了一种更快的方法来复制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);
    }
Run Code Online (Sandbox Code Playgroud)

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);
    }
Run Code Online (Sandbox Code Playgroud)

Sti*_*ony 3

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

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