c# .net bitmap bitmapdata

c# - PixelFormat.Format32bppArgb parece tener un orden de bytes incorrecto



.net bitmap (3)

AFAIK está técnicamente basado en COLORREF (que se usa en Windows GDI / GDI + en todas partes) y que se almacena RGBA en la memoria ... vea http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx

Intento obtener todos los valores de bytes de un mapa de bits (System.Drawing.Bitmap). Por lo tanto bloqueo los bytes y los copio:

public static byte[] GetPixels(Bitmap bitmap){ if(bitmap-PixelFormat.Equals(PixelFormat.Format32.bppArgb)){ var argbData = new byte[bitmap.Width*bitmap.Height*4]; var bd = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); System.Runtime.InteropServices.Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4); bitmap.UnlockBits(bd); } }

Probé esta imagen con una imagen muy simple de 2x2 PNG con píxeles (rojo, verde, azul, blanco) que creé en Photoshop. Debido al formato, esperaba los siguientes valores dentro de argbData:

255 255 0 0 255 0 255 0 255 0 0 255 255 255 255 255

Pero tengo:

0 0 255 255 0 255 0 255 255 0 0 255 255 255 255 255

Pero este es un formato BGRA. ¿Alguien sabe por qué los bytes parecen intercambiados? Por cierto, cuando uso la imagen directamente para un Image.Source como se muestra a continuación, la imagen se muestra correctamente. Entonces, ¿cuál es mi culpa?

<Image Source="D:/tmp/test2.png"/>


En formato de píxel Bpp32Argb. Usted no necesita acceso byte a byte.

Trun Scan0 a un puntero Int32 en un contexto inseguro.

unsafe { var ptr=(int*)bmData.Scan0; }

Puede realizar algunas operaciones de bits como a continuación Para acceder a los canales de color del primer píxel.

Y no hay necesidad de cuidar byte-order.

var a=(ptr[0] & 0xFF000000)>>24; var r=(ptr[0] & 0x00FF0000)>>16; var g=(ptr[0] & 0x0000FF00)>>8; var b=(ptr[0] & 0x000000FF);

Por cierto, puedes trabajar con Color.ToArgb() devuelto int fácilmente.


Los datos de píxeles son ARGB, 1 byte para alfa, 1 para rojo, 1 para verde, 1 para azul. Alfa es el byte más significativo, azul es el menos significativo. En una máquina little-endian, como la suya y muchas otras, el extremo pequeño se almacena primero, por lo que el orden de bytes es bb gg rr aa. Entonces 0 0 255 255 es igual a azul = 0, verde = 0, rojo = 255, alfa = 255. Eso es rojo.

Este detalle del orden de endiancia desaparece cuando se convierte bd.Scan0 en un int * (puntero a entero) ya que los enteros también se almacenan en little-endian.