PixelFormat.Format32bppArgb似乎有错误的字节顺序

时间:2011-11-12 12:33:04

标签: c# .net bitmap bitmapdata

我尝试从Bitmap(System.Drawing.Bitmap)获取所有字节值。因此,我锁定字节并复制它们:

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);
    }
}

我用一个非常简单的2x2 PNG图像测试了这个图像,这个图像是我在Photoshop中创建的像素(红色,绿色,蓝色,白色)。由于格式,我期望argbData中的以下值:

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

但我得到了:

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

但这是一种BGRA格式。有人知道为什么字节似乎被交换了吗? 顺便说一句,当我直接将图像用于Image.Source时,如下所示,图像显示正确。那我的错是什么?

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

3 个答案:

答案 0 :(得分:38)

像素数据为ARGB,alpha为1字节,红色为1,绿色为1,蓝色为1。 Alpha是最重要的字节,蓝色是最不重要的字节。在像您和其他许多人一样的小端机器上,首先存储小端,因此字节顺序为bb gg rr aa。所以0 0 255 255等于蓝色= 0,绿色= 0,红色= 255,alpha = 255.那是红色。

当你将bd.Scan0转换为int *(指向整数的指针)时,这个endian-ness顺序细节会消失,因为整数也存储为little-endian。

答案 1 :(得分:2)

AFAIK技术上基于COLORREF(在Windows GDI / GDI +中使用),并将RGBA存储在内存中......请参阅http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx

答案 2 :(得分:2)

以Bpp32Argb像素格式。你不需要逐字节访问。

在不安全的上下文中将Scan0转发到Int32指针。

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

你可以像下面那样进行一些操作来访问第一个像素的颜色通道。

并且不需要关心字节顺序。

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

顺便说一下,您可以轻松地使用Color.ToArgb()返回int