不透明度が100%未満のView同士の合成について混乱したので少し深く考えてみた
つい最近、alphaが1未満(=100%未満)のView同士を重ねて描画する実装が必要になったんですが、ふと悩んでしまいました。
alpha=0.1
のViewを2つ重ねたら alpha=0.2
になるのか?
結論、なりませんでした。
しかし、恥ずかしながら何故そうならないのかピンときませんでした。
実際にやってみた
真っ黒のレイヤーを3つ用意して、不透明度を80%にしたレイヤー(上)と、不透明度40%にしたレイヤーを2枚重ねた領域(下)の色がなぜ違うのかをサンプルアプリを作りながら考えてる。単純な足し算じゃないのか…? pic.twitter.com/Gb8gNgbKHZ
— べりゅう (@beryu) 2016年7月13日
このアプリは、画面の上部に alpha=0.8
のViewを1枚、画面の下部に alpha=0.4
のViewを2枚配置しただけのアプリです。
構造は下記の図のようになっています。
見て分かるように、 alpha=0.4
のViewを2枚重ねただけでは alpha=0.8
のViewと同じ色にはなっていませんでした。
では、合成した色はどうやって計算されているのか
※不気味な図になったことをお詫びします
Viewのalpha(=不透明度)に1未満を設定した時、そのViewは 1-alpha
分だけ背景の色を透過するということになります。
alphaが1未満のViewが2枚重なっていると、上記の図のように背景が透ける量が乗算する形で減っていきます。
これが、単純に合成したViewのalpha値を足し算したalpha値を持つViewと同じ色にならない理由でした。
では、合成して同じ色になるalphaはどうやって求めるのか
再現したい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とだいたい同じ色に見えるようになりました。
知ってる人からすると常識的な内容だとは思うのですが、恥ずかしながら少し悩んでしまったので、記事にしてみました。
どなたかの助けになれば幸いです。