我想我已經找到了更快的方式來複制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%的時間我們沒有切換pixelformats!/ EndSarcasm)
2)如果兩個bitmaps的步幅不匹配,可能有問題(因爲stride
是複製操作中循環外部的增量器。)此問題會限制以相同步幅複製到位圖。
編輯:我認爲斷言#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);
}
忘了問題,我不明白雙關語?! – LukeHennerley
@LukeHennerley通常,如果你打算使用'LockBits',你可以用'unsafe'代碼來直接訪問內存。我使用'LockBits'而不是'不安全'的代碼。 – AppFzx
這是相當典型的,GDI +總體上具有非常糟糕的例外情況報告,並且容易延遲其報復。改用Bitmap.Clone()。 –