BlendModeについて


今度、Flutterの書籍を発売することになりました。いや、執筆することの大変さは噂で聞いていたけど、本当に辛かったです。その辺りの話は別に書くとして、ここでは、書籍に載せるには「需要が少なそう/カラーじゃないと意味がない」と思って書籍から外したBlendModeについて書きます。このBlendModeですが、公式ドキュメントにも詳しく書いてあるのですが、もっとシンプルにした方が伝わると思い書きました。

頑張って書いたので、宣伝しちゃいます。[こちら](https://www.amazon.co.jp/%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6-Flutter-%E7%9F%B3%E4%BA%95-%E5%B9%B8%E6%AC%A1/dp/4863542941/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=9784863542945&qid=1575725980&sr=8-1)です。12/25に発売予定です。
少しでも誰かの役に立つと嬉しいと思います。

では本題です。

# 概要

BlendModeは色と色の合成モードです。BlendModeの名前付けは、一部Porter-Duffの論文に対応しています。Porter-Duffに関しては、ネット検索すれば出てきますが、別に知らなくて良いです。
BlendModeはenumで、Flutterの様々なところで利用されるのですが、ImageウィジェットのcolorBlendModeプロパティで説明するとわかりやすいです。
この場合は、色と画像の合成です。

```dart
Image.asset(
  'images/flutter.png',
  color: Colors.green.withOpacity(0.5),
  colorBlendMode: BlendMode.srcOver,
),
```

# BlendMode.clear

これを指定すると画像もcolorも表示されません

# BlendMode.src

colorだけが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/7c4475d2-b52f-a5ee-59ac-7eb1e40ee783.png" width="200">

# BlendMode.dst

画像だけが表示されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/1207f241-dcdb-e885-94ad-aa97adc28d9e.png" width="200">

# BlendMode.srcOver

colorを上に画像を下にして合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/dc7c52ed-3fb2-8a88-7b16-177bee9bac00.png" width="200">

# BlendMode.dstOver

画像を上にcolorを下に合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/924533ab-2de1-4f8a-09f0-9de00663d09d.png" width="200">

# BlendMode.srcIn

colorと画像の重なっている部分だけ表示します。colorだけを表示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/38e51f55-3060-4316-1bb8-c9c3e64c1f2e.png" width="200">

# BlendMode.dstIn

colorと画像の重なっている部分だけ表示します。画像だけを表示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/6f53938c-39fa-887d-ae38-a7d20a008a5c.png" width="200">

# BlendMode.srcOut

colorと画像の重なっていない部分だけ表示します。colorだけを表示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/b0509db5-9c22-715f-b399-fc80ec88c0e2.png" width="200">

# BlendMode.dstOut

colorと画像の重なっていない部分だけ表示します。画像だけを表示します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/6067423e-9c2a-ab5e-081a-025f9bddbc97.png" width="200">

# BlendMode.srcATop

colorと画像の重なっている部分だけ表示します。colorを上に画像を下に合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/accb1ad5-bf18-ed66-c4c3-c389aa6f0395.png" width="200">

# BlendMode.dstATop

colorと画像の重なっている部分だけ表示します。画像を上にcolorを下に合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/7ff9812a-9d01-1d6e-7141-b35ad85cbe3d.png" width="200">

# BlendMode.xor

画像の色とcolorをxor演算します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/31102423-32ac-a7db-d572-4a7f9344e1a5.png" width="200">

# BlendMode.plus

画像の色とcolorをplus演算します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/f740f72f-7a32-4e9c-018c-e3bd06568ec5.png" width="200">

# BlendMode.modulate

画像とcolorの色成分を掛け合わせます。これは同じ色か暗い色にしかなりません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/01394f7c-5b3b-6c2d-3e53-6c7e3e81b373.png" width="200">

# BlendMode.screen

画像の色とcolorを反転させて、色成分を掛け合わせ、結果を反転させます。これは同じ色か明るい色にしかなりません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/aab8156a-1a7e-15a0-d296-9c7167f04d90.png" width="200">

# BlendMode.overlay

画像の色の値が小さい場合はこれをcolorの値と乗算し、colorの値が小さい場合はcolorの値の反転と画像の色の値を反転させを乗算してから結果を反転します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/fce681f9-427d-d15e-78db-54baa99902f3.png" width="200">

# BlendMode.darken

各カラーチャンネルから最小値を選択して合成します。 colorを上に画像を下にして合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/ba3f69b3-7efd-149a-6a1c-0f5e7ad46e5a.png" width="200">

# BlendMode.lighten

各カラーチャンネルから最大値を選択して合成します。 colorを上に画像を下にして合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/92f3af3c-6d7c-1e9b-8954-c687354e88dc.png" width="200">

# BlendMode.colorDodge

画像の色を反転させたcolorで除算します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/dc0b7abe-080a-3179-b60b-404ee07b5753.png" width="200">

* BlendMode.colorBurn

画像の色を反転させ、colorで除算し、結果を反転させます。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/0fa9bc37-3fd6-aed9-9a90-5e0f2782a126.png" width="200">

# BlendMode.hardLight

colorの値が小さい場合は、これを画像の色の値と乗算します。画像の色の値が小さい場合は、画像の色の値を反転させ、colorの値を反転させて、それらを乗算して、結果を反転します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/900a191c-2642-e67d-5ee2-10e44f15d197.png" width="200">

# BlendMode.softLight

colorが0.5より小さい場合はcolorDodgeを、大きい場合は、はcolorBurnを使用します。 これは、overlayと似ていますが柔らかい効果をもたらします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/76c22142-cab7-5030-46df-a6a1f2c3a342.png" width="200">

# BlendMode.difference

各チャンネルの大きい方の値から小さい方の値を引きます。 黒を合成しても効果はありません。白を合成すると、もう一方の画像の色が反転します。colorを上に画像を下にして合成します。 効果は、exclusionに近いが濃い色になります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/a29ede66-c8a0-121d-9a0e-571ba35d9947.png" width="200">

# BlendMode.exclusion

2つの画像の合計から2つの画像の積を2倍して引きます。 黒を合成しても効果はありません。白を合成すると、もう一方の画像の色が反転します。colorを上に画像を下にして合成します。  効果は、differenceに近いが柔らかい色になります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/d69db85f-03b9-9b18-3819-72e32535a0bb.png" width="200">

# BlendMode.multiply

アルファチャンネルを含む、画像の色とcolorを乗算します。これは、同じ色またはより暗い色にしかなりません。アルファチャンネルも乗算されるので、透明なピクセルがあると結果も透明なピクセルになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/ddf2ea95-dd92-b6f2-b29e-1693e50de5b1.png" width="200">

# BlendMode.hue

色相をcolor、彩度と明度を画像の色からとります。colorを上に画像を下にして合成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/4f727629-e057-7deb-15b2-929087b197c6.png" width="200">

# BlendMode.saturation

彩度をcolor、色相と明度を画像の色からとります。colorを上に画像を下にして合成します。color内で完全に透明な領域は、画像の色から彩度をとります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/5ba3d569-11e0-7115-96b5-c407e6e346b2.png" width="200">

# BlendMode.color

色相と彩度をcolor、明度を画像の色からとります。colorを上に画像を下にして合成します。color内で完全に透明な領域は、画像の色から色相と彩度をとります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/6e7756cc-784e-095b-2289-c9772351c5c7.png" width="200">

# BlendMode.luminosity

明度をcolor、色相と彩度は画像の色からとります。colorを上に画像を下にして合成します。color内で完全に透明な領域は、画像の色から明度をとります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10494/250292f6-75c3-83de-e5de-0f06a3079fd7.png" width="200">