2012-09-17 9 views
6

Tworzę więc prosty program do przetwarzania obrazu z GUI, C#. Na przykład chcę zmienić kolory obrazu w modelu kolorów HSV, konwertując każdy piksel z RGB iz powrotem.Jak przetwarzać obraz piksel po pikselu za pomocą interfejsu WinAPI w SZYBKIM SPOSOBIE?

Mój program ładuje niektóre zdjęcia według wyboru użytkownika i wyświetla je w jednym z paneli formularza za pomocą kontekstu Grafika. Następnie użytkownik może zrobić coś z tym obrazem, przesuwając paski przewijania, klikając przyciski, wybierając jakiś obszar obrazu itp. Kiedy to zrobi, potrzebuję w czasie rzeczywistym zmienić cały obraz piksel po pikselu. Więc piszę coś takiego:

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) 

I nawet jeśli pracuję z grafiką w pamięci (nie na ekranie), funkcje getPixel i SetPixel działa bardzo wolno (tak, jak mój program działa tak wolno, że profilowane go i wyjaśniłem, że te dwie funkcje spowalniają mój program co najwyżej). Nie mogę przetworzyć dużych zdjęć za kilka chwil, gdy użytkownik przesunie suwak lub zaznaczy pole wyboru.

Proszę pomóc! Co mogę zrobić, aby mój program był szybki? Nie zgadzam się używać innych bibliotek zewnętrznych do grafiki lub zmieniać języka programowania!

+1

+1 za korzystanie profilera, nice! – asawyer

Odpowiedz

7

Tak, funkcje Get/SetPixel działają bardzo wolno. Zamiast tego należy użyć Bitmap.LockBits()/. Zwraca surowe dane bitowe, aby manipulować.

z odniesienia 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

Wow, brzmi dobrze! Spróbuję tego. – Abzac

+0

@Abzac A jeśli to zbyt wolno, możesz zajrzeć do XNA lub zarządzanego directx. – asawyer

+1

Możesz być w stanie wycisnąć więcej wydajności za pomocą niebezpiecznych bloków kodu (chociaż nie wiem, czy byłby to znaczący oszczędności). http://www.bobpowell.net/lockingbits.htm –

Powiązane problemy