C#のWinFormsで画像を扱う場合Bitmapオブジェクトが使われます。こちらをピクセル単位に高速でアクセスする方法として、Bitmapオブジェクト内のピクセルの配列をバイト配列(byte[])へコピーし、コピーした配列をC#からアクセスする方法があります。
グレースケールであれば8bit(1Byte)が1ピクセル(画像上の1ドット)に相当しますが、カラーの場合様々なデータ構造が存在します。とはいえよく目にするのは24bitRGBのカラーとそちらにアルファチャンネル(透明度)をくわえた32bitRGBAがあげられます。
RGBの各色要素に8bitで256諧調の濃淡を表現しそれを3色組み合わせることで2の24乗パターンの色を表現することが出来ます。
表記上RGBAはRed、Green、Blue、Alphaの順番で頭文字を並べていますが、byte配列上ではどのような並びになっているのでしょうか?確認用のプログラムを組んでみたいと思います。
using System.Drawing;
using System.Drawing.Imaging;
class Program
{
static void Main()
{
Bitmap bmp = new Bitmap(32, 32);
BitmapData bmpd = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadWrite,
bmp.PixelFormat
);
int byteWidth = (int)(bmpd.Stride / bmp.Width);
byte[] pixels = new byte[bmpd.Stride * bmp.Height];
System.Runtime.InteropServices.Marshal.Copy(bmpd.Scan0, pixels, 0, pixels.Length);
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmpd.Width; x++)
{
int pos = y * bmpd.Stride + x * byteWidth;
// 以下pixcelsにセットする値の組み合わせを試す。
pixels[pos+0] = 0;
pixels[pos+1] = 0;
pixels[pos+2] = 0;
pixels[pos+3] = 0;
}
}
System.Runtime.InteropServices.Marshal.Copy(pixels,0,bmpd.Scan0,pixels.Length);
bmp.UnlockBits(bmpd);
bmp.Save("patternA.PNG", ImageFormat.Png);
bmp.Dispose();
}
}
パターンA
pixels[pos+0] = 255;
pixels[pos+1] = 0;
pixels[pos+2] = 0;
pixels[pos+3] = 255;
結果
青色が表示されたので、0及び3はBlue又はAlpha
パターンB
pixels[pos+0] = 0;
pixels[pos+1] = 255;
pixels[pos+2] = 0;
pixels[pos+3] = 255;
結果
緑色が表示されたので、1がGreen。ということで0がBlueで3がAlphaの可能性が高い
パターンC
pixels[pos+0] = 0;
pixels[pos+1] = 0;
pixels[pos+2] = 255;
pixels[pos+3] = 255;
パターンD
pixels[pos+0] = 127;
pixels[pos+1] = 127;
pixels[pos+2] = 127;
pixels[pos+3] = 0;
結果
0~2(GBR)に127をセットした場合灰色が出来上がるはずですが、3を0としたため透明となり何もないように見えます。
多分3が透明度(Alpha)だと思われます。
パターンE
pixels[pos+0] = 127;
pixels[pos+1] = 127;
pixels[pos+2] = 127;
pixels[pos+3] = 255;
結果
パターンDと同じく0~2(GBR)に127をセットした状態で3を255にセットしたところ灰色が見えるようになりました。
どうやら3番が透明度で間違いなさそうです。
結論
Bitmapオブジェクトのピクセルのbyte配列は青⇒緑⇒赤⇒透明度(BGRA)の順番に並んでいるようです。
24ビットは確認していませんが多分GBRの順番だと思われます。
コメント