2009年12月14日月曜日

日記ちゃん半透明合成


for (BYTE i=0; i<256; ++i)
{
}


とかやっちゃってたぜ。ふへへ。死ぬがよい。

BYTEはWinDef.hで
typedef unsigned char BYTE;
です。



 半透明合成を実装する必要が出てきたので昔作ったやつを流用。とっても遅いのでどうにかしたい。


DWORD alpha = src >> 24;
DWORD colorRB = ((dest&0xFF00FF)*(256-alpha) + (src&0xFF00FF)*alpha) & 0xFF00FF00;
DWORD colorG = ((dest&0xFF00)*(256-alpha) + (src&0xFF00)*alpha) & 0xFF0000;
dest = ((colorRB | colorG) >> 8) | (dest & 0xFF000000);


 1ピクセル32bit限定でAABBGGRRとデータ並んでいる、普通のDIBデータ。
見てのとおり赤と緑を一度に計算、その後緑を計算し、くっつけて256で割るということを行っている。
各色を別個に計算するよりは速いが、高速化というと微妙なところ。
あと割り算をビットシフトにしてるが普通に「/256」と書いてもコンパイラの最適化がいいようにしてくれると思う。
 アルファ値は下地のままにする。
というか50%の下地に50%を上から合成したらアルファはなんぼになるべきなのか良く分からなかったので。25%? 50%? うーん。
下地100%に上から50%半透明合成をすると、結果100%のままなほうが自然か。
 これでも1024*768を80msぐらいでレンダリングできるのでまったく使えないわけでもない。
dest=srcなべた塗りだと20msぐらいの環境で。

 ちなみに普通の半透明合成の式は
color = (dest*(256-alpha) + src*alpha ) / 256
を各色。



●おまけ


dest = (dest & src) + (((dest ^ src) & 0xfefefefe) >> 1);


 50%限定半透明合成。

他にも、


DWORD color = (dest & 0x00fefefe) + (src & 0x00fefefe);
DWORD mask = color & 0x01010100;
dest = color | (mask - (mask >> 8));


 加算合成。


DWORD mask = ((( ( ((~dest & src)<<1) + ((~dest ^ src) & 0xfefefe) ) & 0x1010100 )>> 8 ) + 0x7f7f7f) ^ 0x7f7f7f;
dest = (dest | mask) - (src | mask);


 減算合成。

 昔どこだかで拾って使っていたもの。
特に加算合成には大変お世話になりました。
とりあえず、自分が考えたわけではないということを明記しなければならない。
それならブログに乗っけるなという話であるが、意外に合成式関係はググっても出てこないので。
誰かのお役に立てば幸い。
 最初の半透明合成だけは自力、ビットも糞もないのが笑える。

0 件のコメント: