はじめてのピクセル演算

http://www.microsoft.com/japan/msdn/library/ja/jpwinui/html/_win32_updatelayeredwindow.asp?frame=true にぶち投げる 32bitBitmap を作るために、今までBitmapとかをごにょごにょしてきました。 実のところ 「描画」 に関しては、Direct3Dでしか行ったことが無かったので、ピクセルレベルでの演算ってのは今やってるのがが始めてだったりします。

いやー、これはこれでメンドイっすね。(笑 ^^;

で「α」「色用」の2つの グレースケールBitmap と 「色用のbmpに乗算する色定数」 を利用して、随時Bitmapを生成するコードを書いてたのですが、自前のコードとしてはこんな形に落ち着きました。


for(; dest != destEnd; ++dest, ++srcA, ++srcC)
{
    const BYTE a = *srcA;
    if(a)
    {
        const BYTE c    = *srcC;
        DWORD dwRB      = dwInvColorRB; // argb の r b を計算する
        DWORD dwG       = dwInvColorG;  // g を計算

        dwRB *=  c;         // 色作って
//        dwRB +=  dwMaskRB;  // 小数点以下切り上げ
        dwRB >>= 8;
        dwRB &=  dwMaskRB;
        dwRB +=  dwColorRB; // 元と合成
        dwRB *=  a;         // αを考慮して
//        dwRB +=  dwMaskRB;  // 小数点以下切り上げ
        dwRB >>= 8;
        dwRB &=  dwMaskRB;

        dwG  *=  c;         // 色作って
//        dwG  +=  dwMaskG;   // 小数点以下切り上げ
        dwG  >>= 8;
        dwG  &=  dwMaskG;
        dwG  +=  dwColorG;  // 元と合成
        dwG  *=  a;         // αを考慮して
//        dwG  +=  dwMaskG;   // 小数点以下切り上げ
        dwG  >>= 8;
        dwG  &=  dwMaskG;


        // a - (a >> 3) -> ちょっと加算合成っぽく
        *dest = (((a - (a >> 3)) << 24) | dwG | dwRB);
    }
    else
    {
        *dest = 0;
    }
}

ベタ書き*1

何をやってるかの一応の解説ですが、基本となる色 RGB と 色用グレースケールBitmap(srcColor) を利用して

  • srcColor == 0 -> RGB
  • srcColor == 255 -> 白 (FFFFFF)

間の値は線形補間して、さらに各ピクセルごとにαを考慮させてます。

で、どうしようかとちょっと悩んだのがコメントアウトしてある所。 256 で割ってるので、そのままだと少し暗くなってしまいます。ので、端数を切り上げてみたりしたのですが、

http://ir9.jp/hd/hd051223_00.png
大して変らんかったわ(ぉ

左右の画像で当然ながら数値的な誤差はあるのですが、ごちゃごちゃしてる画像だと判りづらいですな。 単体で描画するとなったら比較する対象もなくなるので、更に問題なくなるだろうし。


ところで yaneGTL だとテーブルを利用しているという事実はどーしましょーかねー。(死

*1:今はGのコードがちっと違う