画像の合成の手順(プログラミング)



背景の上にキャラクター(背景のオレンジを透過)を合成
ペイント関係のソフトウェアであれば、今のご時世、簡単にできるかもしれない「画像の合成」。
PNG形式ファイルの透過設定を使えば、プログラミングでも関数やライブラリは用意されている。
しかし、BMP形式のファイルを扱う場合や、プログラミングの中で加工されたビットマップ画像となると、やはり合成はすぐにはできない。
透過部分を処理した画像を自分で用意する手間もあるし、決められた画像しか扱えない。
それでは汎用性に欠ける。
ということで、画像の合成方法を手順として書き記してメモが気にしておく。
C++で話を進めていくと、BitBlt()関数を使いこなしていかなければならない。
BOOL BitBlt(
HDC hdcDest, // handle to destination device context
int nXDest, // x-coordinate of destination rectangle's upper-left
int nYDest, // y-coordinate of destination rectangle's upper-left
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
HDC hdcSrc, // handle to source device context
int nXSrc, // x-coordinate of source rectangle's upper-left
int nYSrc, // y-coordinate of source rectangle's upper-left
DWORD dwRop // raster operation code
);
特に最後の dwRop をきちんと使っていかなければならない。
手順としては
(1)キャラクターのマスク画像(白黒)を作成
(2)中間画像(P):キャラクター画像+反転マスク画像
(3)背景画像の上にマスク画像を上書き(AND結合)
(4)背景画像の上に中間画像(P)を上書き(OR結合)
という流れ。
(1)キャラクターのマスク画像(白黒)を作成
まずは、キャラクター画像の透過部分を、自分で決めて塗り潰しておく。ここでは、オレンジ色。
(1)に関しては、ペイント関係のソフトウェアで自作してもいいし、プログラミングで自作してもいい。
マスク画像は、
黒 = イメージ部分
白 = 透過部分
として作成する。
右の図では、キャラクター部分を黒にする。
プログラミングだと、for() 文で全てのピクセルを調べて、オレンジ色だったら白にする、みたいな単純なコードでもいい。

(2)中間画像(P):キャラクター画像+反転マスク画像
マスク画像は大切なので、残しておく。
新しいビットマップを作成して、マスク画像を白黒反転させてコピー転送する。

→(白黒反転)

BitBlt()関数の最後の引数 dwRop = NOTSRCCOPY
(反転した転送元のビットマップと転送先ビットマップにコピーします)
この指定方法で、一発変換で完成。
反転マスク画像を(W)とする。
次に、反転マスク画像(W)の上にキャラクターを上書きする。
ただし、AND結合。
BitBlt()関数の最後の引数 dwRop = SRCAND
(転送元のビットマップと転送先ビットマップのピクセルを論理 AND 演算子で結合します)


AND結合 →
(SRCAND指定)

ビット演算で 0x0000 & 0x**** 何をAND結合しても 0x0000 になる。背景を黒にするのは、この原理。
同様に、白の場合、0xffff & 0x**** = 0x**** になる。
中間画像(P)完成。
(3)背景画像の上にマスク画像を上書き(AND結合)


AND結合 →
(SRCAND指定)

背景画像の上に、マスク画像(最初に作成した画像)を単純にAND結合で上書きする。
dwRop = SRCAND
(4)背景画像の上に中間画像(P)を上書き(OR結合)


OR結合 →
(SRCPAINT指定)

最後に、手順(2)(3)の画像を重ね合わせる。
ただし、今度は、OR結合。
BitBlt()関数の最後の引数 dwRop = SRCPAINT
(転送元のビットマップと転送先ビットマップのピクセルを論理 OR 演算子で結合します)
ビット演算で 0x0000 | 0x**** = 0x**** になる。黒の部分は、相手側の画像になる。
以上、(1)~(4)で合成は完成する。