I try to get all byte values from a Bitmap(System.Drawing.Bitmap). Therefore I lock the bytes and copy them:
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); } }
I tested this Image with a very simple 2x2 PNG image with pixels (red, green, blue, white) that I created in Photoshop. Because of the format, I expected the following values within the argbData:
255 255 0 0 255 0 255 0 255 0 0 255 255 255 255 255
But I got:
0 0 255 255 0 255 0 255 255 0 0 255 255 255 255 255
But this is a BGRA format. Does anybody know why the bytes seems swapped? By the way, when I use the image directly for a Image.Source as shown below, the Image is shown correctly. So what's my fault?
<Image Source="D:/tmp/test2.png"/>
Pixel data is ARGB, 1 byte for alpha, 1 for red, 1 for green, 1 for blue. Alpha is the most significant byte, blue is the least significant. On a little-endian machine, like yours and many others, the little end is stored first so the byte order is bb gg rr aa. So 0 0 255 255 equals blue = 0, green = 0, red = 255, alpha = 255. That's red.
See, paletted png images are actually fully alpha-capable, on a palette level. The png file has a specific extra chunk (the "tRNS" chunk) that can be added to define the alpha of each palette entry. Somehow, when encountering this, the .Net framework applies this alpha correctly, but then insists on treating the image as 32bppARGB.
On a little-endian machine, like yours and many others, the little end is stored first so the byte order is bb gg rr aa. So 0 0 255 255 equals blue = 0, green = 0, red = 255, alpha = 255. That's red. This endian-ness order detail disappears when you cast bd.Scan0 to an int* (pointer-to-integer) since integers are stored little-endian as well.
By the way, analysis of the png chunks showed that that second image is in fact a one-bit-per-pixel image, with a palette of 256 colours. No idea how you managed that. Show activity on this post. When you run the Bitmap constructor, it parses the image file and loads it into an object.
Pixel data is ARGB, 1 byte for alpha, 1 for red, 1 for green, 1 for blue. Alpha is the most significant byte, blue is the least significant. On a little-endian machine, like yours and many others, the little end is stored first so the byte order is bb gg rr aa. So 0 0 255 255 equals blue = 0, green = 0, red = 255, alpha = 255. That's red.
This endian-ness order detail disappears when you cast bd.Scan0 to an int* (pointer-to-integer) since integers are stored little-endian as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With