2009-08-04 13 views

Respuesta

25

Este es un ejemplo completo con ambos métodos, utilizando LockBits() y GetPixel(). Además de los problemas de confianza con LockBits() las cosas pueden ponerse peludas fácilmente.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Drawing; 

namespace BitmapReader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      //Try a small pic to be able to compare output, 
      //a big one to compare performance 
      System.Drawing.Bitmap b = new 
       System.Drawing.Bitmap(@"C:\Users\vinko\Pictures\Dibujo2.jpg"); 
      doSomethingWithBitmapSlow(b); 
      doSomethingWithBitmapFast(b); 
     } 

     public static void doSomethingWithBitmapSlow(System.Drawing.Bitmap bmp) 
     { 
      for (int x = 0; x < bmp.Width; x++) 
      { 
       for (int y = 0; y < bmp.Height; y++) 
       { 
        Color clr = bmp.GetPixel(x, y); 
        int red = clr.R; 
        int green = clr.G; 
        int blue = clr.B; 
        Console.WriteLine("Slow: " + red + " " 
             + green + " " + blue); 
       } 
      } 
     } 

     public static void doSomethingWithBitmapFast(System.Drawing.Bitmap bmp) 
     { 
      Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 

      System.Drawing.Imaging.BitmapData bmpData = 
       bmp.LockBits(rect, 
        System.Drawing.Imaging.ImageLockMode.ReadOnly, 
        bmp.PixelFormat); 

      IntPtr ptr = bmpData.Scan0; 

      int bytes = bmpData.Stride * bmp.Height; 
      byte[] rgbValues = new byte[bytes]; 

      System.Runtime.InteropServices.Marshal.Copy(ptr, 
          rgbValues, 0, bytes); 

      byte red = 0; 
      byte green = 0; 
      byte blue = 0; 

      for (int x = 0; x < bmp.Width; x++) 
      { 
       for (int y = 0; y < bmp.Height; y++) 
       { 
        //See the link above for an explanation 
        //of this calculation 
        int position = (y * bmpData.Stride) + (x * Image.GetPixelFormatSize(bmpData.PixelFormat)/8); 
        blue = rgbValues[position]; 
        green = rgbValues[position + 1]; 
        red = rgbValues[position + 2]; 
        Console.WriteLine("Fast: " + red + " " 
             + green + " " + blue); 
       } 
      } 
      bmp.UnlockBits(bmpData); 
     } 
    } 
} 
+1

Nunca he podido implementar ningún tipo de procesamiento de imágenes usando Get/SetPixel. Siempre * es * demasiado lento, incluso para operaciones triviales como el aumento del brillo general. –

+1

Siempre es demasiado lento cuando las imágenes son grandes. Para imágenes de tamaño de icono, es perfectamente adecuado :-) –

+0

Oh, bueno, sí :-) –

9

Puede cargar la imagen utilizando new Bitmap(filename) y luego usar Bitmap.GetPixel repetidamente. Esto es muy lento pero simple. (Consulte la respuesta de Vinko para ver un ejemplo.)

Si el rendimiento es importante, es posible que desee utilizar Bitmap.LockBits y el código inseguro. Obviamente, esto reduce el número de lugares en los que podría usar la solución (en términos de niveles de confianza) y generalmente es más complejo, pero puede ser lote más rápido.

+0

Wow. Estaba buscando esto hace unas semanas. Definitivamente mirará más en el ejemplo. Gracias por el enlace. – maxwellb

+0

Es mucho más complejo (y bastante más rápido), debe tener en cuenta el PixelFormat de la imagen, comprobar si los datos están o no rellenos y omitir algunos valores en consecuencia. El ejemplo de MSDN no es particularmente útil ya que no menciona nada de esto. –

Cuestiones relacionadas