beryulog

iOSアプリ/サーバーサイド開発者のメモと雑記

不透明度が100%未満のView同士の合成について混乱したので少し深く考えてみた

つい最近、alphaが1未満(=100%未満)のView同士を重ねて描画する実装が必要になったんですが、ふと悩んでしまいました。

alpha=0.1 のViewを2つ重ねたら alpha=0.2 になるのか?

結論、なりませんでした。
しかし、恥ずかしながら何故そうならないのかピンときませんでした。

実際にやってみた

このアプリは、画面の上部に alpha=0.8 のViewを1枚、画面の下部に alpha=0.4 のViewを2枚配置しただけのアプリです。
構造は下記の図のようになっています。 f:id:beryu:20160714005706p:plain

見て分かるように、 alpha=0.4 のViewを2枚重ねただけでは alpha=0.8 のViewと同じ色にはなっていませんでした。

では、合成した色はどうやって計算されているのか

f:id:beryu:20160714012241p:plain ※不気味な図になったことをお詫びします

Viewのalpha(=不透明度)に1未満を設定した時、そのViewは 1-alpha 分だけ背景の色を透過するということになります。
alphaが1未満のViewが2枚重なっていると、上記の図のように背景が透ける量が乗算する形で減っていきます。
これが、単純に合成したViewのalpha値を足し算したalpha値を持つViewと同じ色にならない理由でした。

では、合成して同じ色になるalphaはどうやって求めるのか

f:id:beryu:20160714013221p:plain
再現したいalpha値と、合成する片方のViewのalpha値が決まれば、もう片方のViewのalpha値は次の式で求める事ができます。
例えば、再現したいalpha値=0.8 、合成する片方のViewのalpha値=0.4 だった場合の計算式は下記の通りです。
ソースコードではなく、数学の式です)

0.8 = 0.4 + (1 - 0.4) * x
...
x = 0.66666....

実際にやってみると、 alpha=0.4 のViewに alpha=0.67 のViewを合成すれば alpha=0.8 のViewとだいたい同じ色に見えるようになりました。

知ってる人からすると常識的な内容だとは思うのですが、恥ずかしながら少し悩んでしまったので、記事にしてみました。
どなたかの助けになれば幸いです。