2013-07-21 59 views
2

用戶提供我的應用程序的圖像,從該應用程序需要使掩模:創建圖像掩模

掩模包含在原始圖像中的每個透明像素紅色像素。

我試過如下:

Bitmap OrgImg = Image.FromFile(FilePath); 
Bitmap NewImg = new Bitmap(OrgImg.Width, OrgImg.Height); 
for (int y = 0; y <= OrgImg.Height - 1; y++) { 
    for (int x = 0; x <= OrgImg.Width - 1; x++) { 
     if (OrgImg.GetPixel(x, y).A != 255) { 
      NewImg.SetPixel(x, y, Color.FromArgb(255 - OrgImg.GetPixel(x, y).A, 255, 0, 0)); 
     } 
    } 
} 
OrgImg.Dispose(); 
PictureBox1.Image = NewImg; 

我很擔心在慢電腦的性能。有沒有更好的方法來做到這一點?

+0

我會用完全相同的方法。這是緩慢的,但要記住,你正在處理的像素和它的數量可以相當大。只分析一個圖像應該是任何計算機上的一個非常快速的過程。 – varocarbas

+0

對於非常大的圖像,您可以考慮使用「任務」或「工作線程」,而不是主線程凍結UI直到完成處理。 –

+0

我已經在爲此使用'BackgroundWorker'。 – Elmo

回答

3

如果只是零星地使用,例如使用GetPixel()是完全可以接受的,例如,加載一張圖片。但是,如果您想要進行更嚴肅的圖像處理,最好直接使用BitmapData。一個小例子:

//Load the bitmap 
Bitmap image = (Bitmap)Image.FromFile("image.png"); 

//Get the bitmap data 
var bitmapData = image.LockBits (
    new Rectangle (0, 0, image.Width, image.Height), 
    ImageLockMode.ReadWrite, 
    image.PixelFormat 
); 

//Initialize an array for all the image data 
byte[] imageBytes = new byte[bitmapData.Stride * image.Height]; 

//Copy the bitmap data to the local array 
Marshal.Copy(bitmapData.Scan0,imageBytes,0,imageBytes.Length); 

//Unlock the bitmap 
image.UnlockBits(bitmapData); 

//Find pixelsize 
int pixelSize = Image.GetPixelFormatSize(image.PixelFormat); 

// An example on how to use the pixels, lets make a copy 
int x = 0; 
int y = 0; 
var bitmap = new Bitmap (image.Width, image.Height); 

//Loop pixels 
for(int i=0;i<imageBytes.Length;i+=pixelSize/8) 
{ 
    //Copy the bits into a local array 
    var pixelData = new byte[3]; 
    Array.Copy(imageBytes,i,pixelData,0,3); 

    //Get the color of a pixel 
    var color = Color.FromArgb (pixelData [0], pixelData [1], pixelData [2]); 

    //Set the color of a pixel 
    bitmap.SetPixel (x,y,color); 

    //Map the 1D array to (x,y) 
    x++; 
    if(x >= bitmap.Width) 
    { 
     x=0; 
     y++; 
    } 

} 

//Save the duplicate 
bitmap.Save ("image_copy.png"); 
+1

而不是'x> = 100'它應該是'x> = bitmap.Width'... – tzachs

+0

我知道這是舊的,但有人可能會發現它稍後有用。 –

+0

我知道這是舊的,但有人可能會稍後發現它有用。如果你要在C#中談論Bitmap速度,那麼你需要明白,在for循環中,你不應該使用bitmap.Width,因爲C#在訪問時速度非常慢。相反,請將局部變量設置爲Bitmap.Width,並在循環比較中使用該變量。快多了。 Vadim也是正確的,因爲鎖定內存要快得多。 –

1

這種方法確實很慢。更好的方法是使用Lockbits並直接訪問底層矩陣。看看http://bobpowell.net/lockingbits.aspxhttp://www.mfranc.com/programming/operacje-na-bitmapkach-net-1/http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx或其他關於鎖定位在StackOverflow中的文章。

這是一個稍微複雜一點,因爲你必須直接使用字節(如果你使用RGBA,每個像素4個),但性能提升很重要,非常值得。另一個說明 - OrgImg.GetPixel(x,y)很慢,如果你堅持這樣(而不是鎖定位),確保你只使用它一次(它可能已經優化,只是檢查是否有差異)。