亀岡的プログラマ日記

京都のベッドタウン、亀岡よりだらだらとお送りいたします。

WritableBitMapをちびちびさわってみる。その2。

昨日は白黒の表示までだったので、カラーの表示をしてみましょう。

まず、ピクセルフォーマットをカラー対応のものにします。使いやすいのはBgr32でしょう。

Bgra32 ピクセル形式を取得します。 Bgra32 は、bits per pixel (BPP) が 32 の sRGB 形式です。 各カラー チャネル (青、緑、赤、およびアルファ) に割り当てられるbits per pixel (BPP) は 8 です。

というわけで、PixelFormatをBgra32にしてWritableBitmapを生成します。

            const int COLS = 10;
            const int ROWS = 10;
            var bitmap = new WriteableBitmap(COLS, ROWS, 96, 96,
                                     PixelFormats.Bgra32, null);

各ピクセル値は32bitになっているので、ピクセルデータ格納の配列はuintになります。

             uint[] pixels = new uint[COLS * ROWS];

各ピクセル値はBGRA=Blue → Green → Red → Alphaの順番に8bitずつシフトして並んでいるので・・・

            redVal = redVal << 16;
            greenVal = greenVal << 8;
            blueVal = blueVal; //blueは変化なし
            alphaVal = alphaVal << 24;
            pixels[index] = redVal + greenVal + blueVal + alphaVal; 

こんな感じでビットシフトして足し合わせるとちゃんと出来ます。

あとはWritePixelなのですが・・・これの第3引数をちょっと計算しないといけません。

sourceBufferStride:型: System.Int32 入力バッファー内のストライド (バイト単位)。

ストライドと言われてもよくわかりませんが、要するに一行内のバイト数、ということになります。
PixelFormatクラスにはBitsPerPixelプロパティがあるので・・・

            var stride = (COLS * bitmap.Format.BitsPerPixel) / /*bit->Byte*/8; 

普通はこうでいいのですが、実はBitsPerPixelが8以下、すなわちbyte型以下という場合があり、その場合は配列の要素に2つ以上のデータが入ることになります。ただし行の先頭とByte境界は必ず一致しなければならないらしく、中途半端なbitを落とすために。

            var stride = (COLS * bitmap.Format.BitsPerPixel + /*Byte境界と行頭を一致させる*/7) / /*bit->Byte*/8; 

がより汎用的となります。あとは、WritePixelするだけ。

            bitmap.WritePixels(
                new Int32Rect(0, 0, COLS, ROWS), //書きこむ領域(ここでは全体)
                pixels, //書きこむデータ
                stride,   //列幅(バイト単位)
                0       //オフセット
                );

見慣れてくるとなんのことはなく簡単ですよね、これ。