4304


[PorterDuff.Mode](http://developer.android.com/reference/android/graphics/PorterDuff.Mode.html)のドキュメントを見るとADD,
OVERLAYだけ具体的な式が記述されておらず、SRC・DSTのARGB値にどのような計算が行われるのかわかりません。 ADDには「Saturate(S +
D)」と書いてありますがこの意味がわかりません。[Sa+Da, Sc+Dc] みたいな感じになるのでしょうか？
OVERLAYに至っては何も書いてありません…


CC BY-SA 3.0
2015-01-08T12:15:16.990
4297
2015-01-08T15:22:17.833
450
question
android
PorterDuff.Mode.ADDとPorterDuff.Mode.OVERLAYの計算結果


困ったときのソースコードということで、[PorterDuffUtility#getComposite()](http://androidxref.com/5.0.0_r2/xref/frameworks/base/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java#60)
→
[BlendComposite#getBlenderFor()](http://androidxref.com/5.0.0_r2/xref/frameworks/base/tools/layoutlib/bridge/src/android/graphics/BlendComposite.java#356)
と辿ると具体的な実装があります。

`ADD`： Saturate(S +
D)は飽和加算とよばれる演算です。S+D加算後のRGBA各値が最大値255を超えないようクリッピングされます。「画像の足し算」を何も考慮せずに行ってしまうと、加算後のpixel値が255（8bitで表現可能な最大値）を超えてしまい、足し算前よりも小さなpixel値が算出されてしまいます（例:
128+192=64）。このような状況を避けるために、映像系などのマルチメディア処理では飽和演算が良く用いられます。

[code]

    public int[] blend(int[] src, int[] dst, int[] result) {
      for (int i = 0; i < 4; i++) {
        result[i] = Math.min(255, src[i] + dst[i]);
      }
      return result;
    }
    
[/code]

`OVERLAY`：下式で実装されています。直感的には理解しづらいですが、文字通り「画像のオーバーレイ」を計算しているようです。RGB値では乗算を、Α(alpha)値では飽和加算を行うことで、2つの画像をブレンドしています。（画像が描かれた2つの半透明スライドを重ね合わせるニュアンスですかね）

[code]

    public int[] blend(int[] src, int[] dst, int[] result) {
      for (int i = 0; i < 3; i++) {
        result[i] = dst[i] < 128 ? dst[i] * src[i] >> 7 :
          255 - ((255 - dst[i]) * (255 - src[i]) >> 7);
      }
      result[3] = Math.min(255, src[3] + dst[3]);
      return result;
    }
    
[/code]


CC BY-SA 3.0
2015-01-08T15:11:03.663
4304
2015-01-08T15:22:17.833
2015-01-08T15:22:17.833
49
49
4297
answer