2012-09-17 36 views
6

所以,我用C#做了一些簡單的圖像處理程序。例如,我想更改HSV顏色模型中的圖像顏色,將每個像素從RGB轉換回來。如何使用WinAPI以快速方式逐個像素地處理圖像?

我的程序通過用戶選擇加載一些圖片,並使用其圖形上下文將其顯示在窗體的一個面板中。然後,用戶可以通過移動滾動條,單擊按鈕,選擇一些圖像區域等來對此圖片進行操作。當他這樣做時,我需要實時更改所有圖片的像素。所以,我寫的是這樣的:

for (int x = 0; x < imageWidth; x++) 
    for (int y = 0; y < imageHeight; y++) 
     Color c = g.GetPixel(x, y); 
     c = some_process_color_function_depending_on_user_controls(c); 
     g.SetPixel(x, y) 

即使我在存儲器(未在屏幕上)與圖形工作,職能GetPixel和SetPixel工作很慢(所以,我的程序運行很慢,我異形它,並解釋說這兩個函數最多會放慢我的程序)。所以,當用戶移動滑塊或檢查複選框時,我無法在幾秒鐘內處理大圖片。

請幫忙!我能做些什麼來使我的計劃變得更快?我不同意將其他第三方庫用於圖形或更改編程語言!

+1

+1使用探查,不錯! – asawyer

回答

7

是的,Get/SetPixel函數非常慢。改爲使用Bitmap.LockBits()/UnlockBits()。它返回原始位數據供您操作。

從MSDN參考:

private void LockUnlockBitsExample(PaintEventArgs e) 
{ 

    // Create a new bitmap. 
    Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg"); 

    // Lock the bitmap's bits. 
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 
    System.Drawing.Imaging.BitmapData bmpData = 
     bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, 
     bmp.PixelFormat); 

    // Get the address of the first line. 
    IntPtr ptr = bmpData.Scan0; 

    // Declare an array to hold the bytes of the bitmap. 
    // This code is specific to a bitmap with 24 bits per pixels. 
    int bytes = bmp.Width * bmp.Height * 3; 
    byte[] rgbValues = new byte[bytes]; 

    // Copy the RGB values into the array. 
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes); 

    // Set every red value to 255. 
    for (int counter = 2; counter < rgbValues.Length; counter+=3) 
     rgbValues[counter] = 255; 

    // Copy the RGB values back to the bitmap 
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes); 

    // Unlock the bits. 
    bmp.UnlockBits(bmpData); 

    // Draw the modified image. 
    e.Graphics.DrawImage(bmp, 0, 150); 

} 
+0

哇,聽起來不錯!我會試試看。 – Abzac

+0

@Abzac如果這太慢,你可以看看XNA或託管directx。 – asawyer

+1

您可以使用不安全的代碼塊來擠出更多性能(儘管我不知道這是否會大幅節省)。 http://www.bobpowell.net/lockingbits.htm –