Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PixelFormat.Format32bppArgb seems to have wrong byte order

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"/> 
like image 395
0xBADF00D Avatar asked Nov 12 '11 12:11

0xBADF00D


People also ask

What is the byte order of pixel pixel data?

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.

Why is my PNG image 32bppargb instead of 32 bpp?

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.

What is the Order of bytes in a little endian machine?

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.

How many colours are in a bitmap image?

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.


1 Answers

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.

like image 61
Hans Passant Avatar answered Sep 28 '22 18:09

Hans Passant