我尝试从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"/>
答案 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
。