2013-02-07 52 views
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%的時間我們沒有切換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); 
    } 
+5

忘了問題,我不明白雙關語?! – LukeHennerley

+0

@LukeHennerley通常,如果你打算使用'LockBits',你可以用'unsafe'代碼來直接訪問內存。我使用'LockBits'而不是'不安全'的代碼。 – AppFzx

+3

這是相當典型的,GDI +總體上具有非常糟糕的例外情況報告,並且容易延遲其報復。改用Bitmap.Clone()。 –

回答

3

改爲使用Bitmap.Clone()。 GDI +往往不會報告異常情況,所產生的錯誤將很難追蹤。

將圖像複製到一個位圖非常快速方法是用Graphics.DrawImage()只要你不轉換像素格式或縮放圖像

相關問題