web-dev-qa-db-ja.com

PixelFormat.Format32bppArgbのバイト順序が間違っているようです

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

この画像を、Photoshopで作成したピクセル(赤、緑、青、白)の非常に単純な2x2PNG画像でテストしました。形式のため、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"/>
23
0xBADF00D

ピクセルデータはARGB、アルファ用に1バイト、赤用に1、緑用に1、青用に1です。アルファは最上位バイトで、青は最下位バイトです。あなたや他の多くのようなリトルエンディアンのマシンでは、リトルエンドが最初に格納されるため、バイト順序はbb gg rraaになります。したがって、0 0 255255は青= 0、緑= 0、赤= 255、アルファ= 255に等しくなります。それは赤です。

整数もリトルエンディアンで格納されるため、bd.Scan0をint *(pointer-to-integer)にキャストすると、このエンディアン順の詳細は表示されなくなります。

40
Hans Passant

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を簡単に操作できます。

3
IlPADlI

AFAIKは、技術的にはCOLORREF(Windows GDI/GDI +で使用されています)に基づいており、RGBAをメモリに保存しています... http://msdn.Microsoft.com/en- us/library/dd183449%28VS.85%29.aspx

2
Yahia