2012-12-26 71 views
3

我有3個System.Drawing.Bitmap對象。 RGB前景,RGB背景和每像素單個字節蒙版圖像,其中0代表背景像素,1代表前景像素。所有三個都是相同的尺寸。圖像蒙板過濾器

我選擇使用位圖對象,因爲我需要最終在MonoTouch和MonoDroid中運行此代碼。如果需要,我可以重新考慮。

我已經優化了代碼,但仍然顯得很慢。這也是整個操作中最慢的部分,所以我想優化它。我也不禁想到有一些祕密方法可以爲我做這一切。

如果有幫助。在此之前,所有3個都是byte [],我將它們變成圖像並重新調整尺寸以保持一致。如果我能做得更好一步,那就讓我知道。

下面的代碼是我目前正在使用的,並基本上更新與適當的前景像素的背景圖像。

 BitmapData backgroundData = background.LockBits(new System.Drawing.Rectangle(0, 0, background.Width, background.Height), ImageLockMode.ReadOnly, background.PixelFormat); 
     int backgroundPixelSize = GetPixelSize(backgroundData); 

     BitmapData foregroundData = foreground.LockBits(new System.Drawing.Rectangle(0, 0, foreground.Width, foreground.Height), ImageLockMode.ReadOnly, foreground.PixelFormat); 
     int foregroundPixelSize = GetPixelSize(foregroundData); 

     BitmapData maskData = mask.LockBits(new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadOnly, mask.PixelFormat); 
     //int maskPixelSize = GetPixelSize(maskData); 

     for (int y = 0; y < background.Height; y++) 
     { 
      byte* backgroundRow = (byte*)backgroundData.Scan0 + (y * backgroundData.Stride); 
      byte* foregroundRow = (byte*)foregroundData.Scan0 + (y * foregroundData.Stride); 
      byte* maskRow = (byte*)maskData.Scan0 + (y * maskData.Stride); 

      for (int x = 0; x < background.Width; x++) 
      { 
       // Check if the mask byte is set 
       if (maskRow[x] > 0) 
       { 
        // Copy the bytes over 
        for (int p = 0; p < backgroundPixelSize; p++) 
        { 
         backgroundRow[x * backgroundPixelSize + p] = foregroundRow[x * foregroundPixelSize + p]; 
        } 
       } 
      } 
     } 

更新: 的兩個圖像是每個像素的3個字節和掩模圖像是每個像素1個字節。

+0

我編輯了自己的冠軍。請參閱:「[應該在其標題中包含」標籤「](http://meta.stackexchange.com/questions/19190/)」,其中的共識是「不,他們不應該」。 –

+2

如果您知道圖像將是24位RGB,則刪除內部的'backgroundPixelSize'循環會立即爲您提供相當不錯的加速。 –

+0

@CoryNelson我會測試看看。循環確實有一個不需要的小開銷。當我不一定需要時,我一般會考慮。 – Telavian

回答

0

您可以試試這段代碼。我認爲它更加快速和清晰(所有三幅圖像都具有相同的尺寸)。

BitmapData backgroundData = background.LockBits(
    new System.Drawing.Rectangle(0, 0, background.Width, background.Height), 
    ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); 

BitmapData foregroundData = foreground.LockBits(
    new System.Drawing.Rectangle(0, 0, foreground.Width, foreground.Height), 
    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

BitmapData maskData = mask.LockBits(
    new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), 
    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

uint* backgroundPtr = (uint*)backgroundData.Scan0; 
uint* foregroundPtr = (uint*)foregroundData.Scan0; 
uint* maskPtr = (uint*)maskData.Scan0; 

int dataLength = backgroundData.Height * backgroundData.Width; 

for (int i = 0; i < dataLength; i++) 
    if (maskPtr[i] > 0) 
     backgroundPtr[i] = foregroundPtr[i]; 

UPDATE

此外,也可以使用面膜的PixelFormat:

BitmapData maskData = mask.LockBits(
    new System.Drawing.Rectangle(0, 0, mask.Width, mask.Height), 
    ImageLockMode.ReadOnly, mask.PixelFormat); 
byte* maskPtr = (byte*)maskData.Scan0; 

int dataLength = backgroundData.Height * backgroundData.Width; 
for (int i = 0; i < dataLength; i++) 
    if (maskPtr[i] > 0) 
     backgroundPtr[i] = foregroundPtr[i]; 
+0

所有3個尺寸相同,但掩模圖像是每個像素單個字節。另外兩個是嚴格的RGB,每個像素有24個字節。 – Telavian

+0

@Telavian,我想我的代碼可以適用於你的情況,因爲'LockBits'方法準備適當的數組依賴於'PixelFormat'參數(在我的代碼'Format32bppArgb'中)。 –

+0

我不認爲你可以經過線性,因爲有時每行都被填充以對齊單詞邊界。因此需要步幅值。 http://bobpowell.net/lockingbits.htm – Telavian