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)PixelFormat2つのビットマップのが異なる場合、このメソッドは常に正しくコピーされるとは限りません。ただし、LockBitspixelformatを指定する必要があるため、これは処理されているようです。(もしそうなら、ピクセルフォーマットを切り替えていない他の99.9%の時間、そのオーバーヘッドにご期待ください!/ EndSarcasm)

2)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