2012-09-17 34 views
6

Por lo tanto, hago un programa simple de procesamiento de imágenes con GUI, C#. Por ejemplo, quiero cambiar los colores de la imagen en el modelo de color HSV, convirtiendo cada píxel de RGB y viceversa.¿Cómo se procesa la imagen píxel por píxel con WinAPI de forma RÁPIDA?

Mi programa carga algunas imágenes por elección del usuario y las muestra en uno de los paneles del formulario utilizando su contexto de Gráficos. Entonces el usuario puede hacer algo con esta imagen moviendo las barras de desplazamiento, haciendo clic en los botones, seleccionando un área de imagen, etc. Cuando lo haga, necesito cambiar en tiempo real todas las imágenes píxel por píxel. Por lo tanto, escribo algo como:

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) 

E incluso si trabajo con gráficos en la memoria (no en la pantalla), funciona GetPixel y SetPixel funciona muy lento (así, como mi programa funciona tan lento, me perfilado se , y explicó que estas dos funciones están ralentizando mi programa como máximo). Por lo tanto, no puedo procesar imágenes grandes en un momento dado mientras el usuario mueve el control deslizante o marca la casilla de verificación.

Por favor ayuda! ¿Qué puedo hacer para que mi programa sea rápido? ¡No estoy de acuerdo en utilizar otras bibliotecas de terceros para gráficos o cambiar el lenguaje de programación!

+1

+1 para el uso de un generador de perfiles, agradable! – asawyer

Respuesta

7

Sí, las funciones Get/SetPixel son muy lentas. Use Bitmap.LockBits()/UnlockBits() en su lugar. Devuelve los datos de bit sin formato para que los manipule.

De la referencia de 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

Guau, ¡suena bien! Lo intentaré. – Abzac

+0

@Abzac Y si esto es demasiado lento, puede examinar XNA o directx administrado. – asawyer

+1

Es posible que pueda exprimir más rendimiento utilizando bloques de código inseguros (aunque no sé si sería un ahorro significativo). http://www.bobpowell.net/lockingbits.htm –

Cuestiones relacionadas