ぐぐっても良い資料が見つからなかったので(こんなの説明されなくてもすぐ分かるって?)置いておきます。Photoshopのレイヤー結合と同じようなことをしたい場合に有用です。あと、あまり確認していないのでPhotoshopの挙動と食い違っていたらごめん。
各変数名は次の語の頭文字を表すものとする。
funcは不透明度を持たない色同士の混合に使う関数とする。例えば加算合成の場合、func(Bc, Fc)=min(1, Bc + Fc)。これがPhotoshopのブレンドモードに対応する。
色や不透明度の値は[0, 1]の範囲(0%から100%の範囲)に収まるものとする。色の値にはアルファ値をあらかじめ乗じないものとする(いわゆるストレートアルファ。乗算済みアルファでは無いものとする)。
Ca = Fa+(1-Fa)*Ba = 1-(1-Fa)*(1-Ba) = Fa*Ba + Fa*(1-Ba) + (1-Fa)*Ba Cc =( Fa *Ba * func(Bc,Fc) + Fa *(1-Ba) * Fc + (1-Fa)*Ba * Bc ) / Ca ※ただし、Ca==0のときCcは不定(何の値でも良い)。 ※Caの式は三つ書いておいたが、どれも同じなので用途に応じて選んで欲しい。
二枚の色つきガラス板F、Bを想像する。それぞれの不透明度(光を遮る率)はFaとBa。色はFcとBc。
今、Fを手前、Bを奥にして重ねて、Bの後ろから光を当て、Fの前にどれだけ光が通るかを考える。BにBaだけ遮られ、1-Baだけ通過する。1-Baになった光が FにFaだけ遮られ、最終的に(1-Ba)(1-Fa)だけ通過する。つまり透過度(透明度)は(1-Ba)(1-Fa)。不透明度はその残りの割合なので(1- (1-Ba)(1-Fa))。例えばBaが60%、Faが75%とすると、Bによって60%が遮られ、40%が通過する。通過した40%のうち、Fによって75%が遮られ、25%が通過する。最終的に通過するのは40%のうち25%なので、0.4*0.25=0.1、つまり10%となる。残り90%はFとBによって遮られる。つまり、不透明度は90%となる。
目に入る色のうち、Faの割合はFc、(1-Fa)はその後ろの色、(1-Fa)のうちBaの割合はBc。(1-Fa)のうち(1-Ba)の割合はBの後ろの色。まとめると、次のようになる。
(目に入る色) = Fa*Fc + (1-Fa)*Ba*Bc + (1-Fa)*(1-Ba)*(Bの後ろの色)
通常合成の場合はこれでよいが、加算合成や乗算合成などの特殊な合成では不十分。
加算合成や乗算合成といった合成方法は完全不透明である純粋な色同士に対して適用する計算なので、Fa*Baの割合だけに適用する。余るFa*(1-Ba)の部分についてはFcをそのまま適用する。以上のことを考慮すると次のようになる。
(目に入る色) = Fa*Ba*func(Bc,Fc) + Fa*(1-Ba)*Fc + (1-Fa)*Ba*Bc + (1-Fa)*(1-Ba)*(Bの後ろの色)
最終的に求めたいのはFとBをfuncで合成した時の色と不透明度なので、「Bの後ろの色」に関する部分を外し、既に乗じてある不透明度をキャンセルするためにCaで割ると、最初に示した式となる。この部分は少し分かりづらいかもしれないが、「Bの後ろの色」の前に掛かっている係数が(1-Ca)と同じであること注目すれば分かるかもしれない。
Caが0のときは完全に透明と言うことなので、色は一つに定まらない。
ちなみに、この合成方法は結合法則を満たさない場合があるので注意すること(func次第?)。例えばA、B、Cという三つのピクセル(又はレイヤー)を一つに合成する場合、AとBを先に合成した場合とBとCを先に合成した場合とで結果が異なる場合がある。Photoshopでレイヤーの結合を色々試したことがある人は経験的に分かると思う。
func(Bc, Fc) = Fc
func(Bc, Fc) = min(1, Bc + Fc)
func(Bc, Fc) = Bc * Fc
Photoshopのブレンドモードに対応した合成方法の式については、osakana.factory - ブレンドモード詳説が詳しい。