「加算合成」と「加算 (発光) 合成」の違い

「加算合成」"Linear Dodge / Add" と「加算 (発光) 合成」"Add (Glow)" の違いを式で説明しているものが見当たらなかったため、計算と検証をしてみました。
「加算合成は `src + dest`」としか説明していない記事が多いですが、アルファ値を考慮する場合はこんなに簡単な式になりません。

本記事では、アルファ値 $ \alpha $ と色 $ C $ はどちらも $ [0, 1] $ の範囲で正規化されていると仮定します。
(`max` や `min` の中の定数 `1` を `255` に読み替える等、注意。)

範囲外の値になる場合は 0 から 1 の範囲内に切り詰めます。

# 0. まとめ

アルファ値と色を以下の変数で置きます。いずれも $ [0, 1] $ の範囲で正規化されているとします。

|変数|説明|
|---|---|
|$\alpha$|合成後のアルファ値|
|$C$|合成後の色|
|$\alpha_b$, $\alpha_f$|後ろと手前の画像のアルファ値|
|$C_b$, $C_f$|後ろと手前の画像の色|

画像合成の理論式 (一般化された式に係数とブレンド関数を代入した式) で考えると、「加算合成」と「加算 (発光) 合成」の式はそれぞれ以下の通りになります。

加算合成：

```math
\begin{align}
\alpha &=\alpha_b \alpha_f + \alpha_b (1 - \alpha_f) + (1 - \alpha_b) \alpha_f \tag{7} \\
&= \alpha_b + \alpha_f - \alpha_b \alpha_f \\
C &= \frac{\alpha_b \alpha_f min(1, C_b + C_f) + \alpha_b (1 - \alpha_f) C_b + (1 - \alpha_b) \alpha_f C_f}{\alpha} \tag{8}
\end{align}
```

加算 (発光) 合成：

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f \tag{12} \\
C &= \frac{\alpha_b C_b + \alpha_f C_f}{\alpha} \tag{13}
\end{align}
```

※ CLIP STUDIO PAINT や FireAlpaca 等では計算式が異なります (※後述) 。
※ CLIP STUDIO PAINT と FireAlpaca での「加算合成」「加算 (発光) 合成」は、後景が不透明の場合に理論式と一致します。

# 1. 理論式での違い

## 1.1. 画像合成の理論式

画像合成の式は一般に

```math
\begin{align}
\alpha &= \alpha_b F_b + \alpha_f F_f \tag{1} \\
C_f' &= \alpha_b B(C_b, C_f) + (1 - \alpha_b) C_f \tag{2} \\
C &= \frac{\alpha_b F_b C_b + \alpha_f F_f C_f'}{\alpha} \tag{3}
\end{align}
```

で表されます。

ただし、アルファ値と色以外の変数は以下の表のようになります。

|変数|説明|
|---|---|
|$B(C_b, C_f)$|ブレンド関数 (アルファ値を考慮しない)|
|$F_b$, $F_f$|Porter Duff 演算の定数 (※後述)|
|$C_f'$|ブレンド後コンポジット前の色|

参考「[アルファ値を含むブレンドモードの画像合成の計算式 - Qiita](https://qiita.com/kerupani129/items/4bf75d9f44a5b926df58)」

参考「[Compositing and Blending Level 1](https://www.w3.org/TR/compositing-1/)」(※式中の $C$ と $c$ の大文字小文字で意味が異なるので注意。一部大文字と小文字の間違いあり)

## 1.2. 「加算合成」の理論式

「加算合成」"Linear Dodge / Add" は「Linear Dodge / Add ブレンド & Source Over コンポジット」する合成になります。よって

```math
\begin{align}
B(C_b, C_f) &= min(1, C_b + C_f) \tag{4} \\
F_b &= 1 -\alpha_f \tag{5} \\
F_f &= 1 \tag{6}
\end{align}
```

を (1), (2), (3) 式に代入して

```math
\begin{align}
\alpha &= \alpha_b (1 -\alpha_f) + \alpha_f \\
C_f' &= \alpha_b min(1, C_b + C_f) + (1 - \alpha_b) C_f \\
C &= \frac{\alpha_b (1 -\alpha_f) C_b + \alpha_f C_f'}{\alpha}
\end{align}
```

より

```math
\begin{align}
\alpha &=\alpha_b \alpha_f + \alpha_b (1 - \alpha_f) + (1 - \alpha_b) \alpha_f \tag{7} \\
&= \alpha_b + \alpha_f - \alpha_b \alpha_f \\
C &= \frac{\alpha_b \alpha_f min(1, C_b + C_f) + \alpha_b (1 - \alpha_f) C_b + (1 - \alpha_b) \alpha_f C_f}{\alpha} \tag{8}
\end{align}
```

になります。

## 1.3. 「加算 (発光) 合成」の理論式

「加算 (発光) 合成」"Add (Glow)" は、画像処理ソフトウェアによって実装が異なりますが、「Normal ブレンド & Plus / Lighter コンポジット」(Lighten ブレンドでない) する挙動に近い場合が多いです。よって

```math
\begin{align}
B(C_b, C_f) &= C_f \tag{9} \\
F_b &= 1 \tag{10} \\
F_f &= 1 \tag{11}
\end{align}
```

を (1), (2), (3) 式に代入して

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f \\
C_f' &= \alpha_b C_f + (1 - \alpha_b) C_f \\
C &= \frac{\alpha_b C_b + \alpha_f C_f'}{\alpha}
\end{align}
```

より

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f \tag{12} \\
C &= \frac{\alpha_b C_b + \alpha_f C_f}{\alpha} \tag{13}
\end{align}
```

になります。

## 1.4. 理論式での違い

- $C_b + C_f \leqq 1$ のとき、どちらの合成も $ \alpha C = \alpha_b C_b + \alpha_f C_f $ が成り立ち、$\alpha C$ が一致
- $C_b + C_f > 1$ のとき、「加算合成」より「加算 (発光) 合成」の方が $\alpha C$ が大きくなる
- $\alpha_b + \alpha_f - \alpha_b \alpha_f \leqq \alpha_b + \alpha_f$ より、$\alpha C$ の一致の有無とは別に、「加算合成」より「加算 (発光) 合成」の方が $\alpha$ が大きくなるかまたは等しくなる

「加算合成」と「加算 (発光) 合成」は $\alpha C$ に関して似た動作をしますが、「加算 (発光) 合成」の方が「$C$ の上限」と「$\alpha$ の上限」が大きく、「加算合成」より明るいかまたは等しくなることが分かります。

## 1.5. 後景が不透明のとき

$\alpha_b = 1$ (後景が不透明) のとき、どちらも $\alpha = 1$ が成り立ちます。

このとき「加算合成」の色は

```math
C = \alpha_f min(1, C_b + C_f) + (1 - \alpha_f) C_b \tag{14}
```

になり、「加算 (発光) 合成」の色は

```math
C = C_b + \alpha_f C_f \tag{15}
```

になります。

# 2. 「加算合成」の理論式でブレンド関数の上限をなくした式 (理論式でなくなる)

理論式ではブレンド関数は「アルファ値を考慮せずに合成した色」でなければならず、値域の範囲を超える場合は切り詰められなければなりませんが、あえて値域を制限しないことでも「加算 (発光) 合成」に近い式が作れます。

## 2.1. コンポジット前の色の範囲を制限しない場合

加算合成のブレンド関数の値域の制限をなくして

```math
\begin{align}
B(C_b, C_f) &= C_b + C_f \tag{16} \\
F_b &= 1 -\alpha_f \tag{17} \\
F_f &= 1 \tag{18}
\end{align}
```

を (1), (2), (3) 式に代入すると

```math
\begin{align}
\alpha &= \alpha_b (1 -\alpha_f) + \alpha_f \\
C_f' &= \alpha_b (C_b + C_f) + (1 - \alpha_b) C_f \\
C &= \frac{\alpha_b (1 -\alpha_f) C_b + \alpha_f C_f'}{\alpha}
\end{align}
```

より

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f - \alpha_b \alpha_f \tag{19} \\
C &= \frac{\alpha_b C_b + \alpha_f C_f}{\alpha} \tag{20}
\end{align}
```

になります。

## 2.2. コンポジット前の色の範囲を制限する場合

$B(C_b, C_f) \in [0, 1]$ の場合は常に $C_f' \in [0, 1]$ が成り立ちますが、ブレンド関数の値域を制限しないと $C_f'$ が $[0, 1]$ の範囲を超えるため、$\alpha$ や $C$ だけでなく $C_f'$ の範囲も切り詰める方法も考えられます。

(16), (17), (18) 式を (1), (2), (3) 式に代入し、(2) 式の $C_f'$ の範囲を $[0, 1]$ に制限すると

```math
\begin{align}
\alpha &= \alpha_b (1 -\alpha_f) + \alpha_f \\
C_f' &= min \left( 1, \alpha_b (C_b + C_f) + (1 - \alpha_b) C_f \right) \\
C &= \frac{\alpha_b (1 -\alpha_f) C_b + \alpha_f C_f'}{\alpha}
\end{align}
```

より

```math
\begin{align}
\alpha &=\alpha_b (1 - \alpha_f) + \alpha_f \tag{21} \\
&= \alpha_b + \alpha_f - \alpha_b \alpha_f \\
C &= \frac{\alpha_b (1 - \alpha_f) C_b + \alpha_f min(1, \alpha_b C_b + C_f)}{\alpha} \tag{22}
\end{align}
```

になります。

# 3. CLIP STUDIO PAINT での式 (推定)

CLIP STUDIO PAINT ver.1.9.4 で色を調べ、式を推定しました。

## 3.1. 「加算合成」の式 (推定)

理論式に少し近い形をしていますが、Source Over コンポジットを 2 重に行うような式になります。

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f - \alpha_b \alpha_f \tag{23} \\
C_b' &= \frac{\alpha_f min(1, C_b + C_f) + \alpha_b (1 - \alpha_f) C_b}{\alpha} \tag{24} \\
C &= \frac{\alpha_b C_b' + (1 - \alpha_b) \alpha_f C_f}{\alpha} \tag{25}
\end{align}
```

## 3.2. 「加算 (発光) 合成」の式 (推定)

(24) 式で $C_b + C_f$ の範囲の制限をなくし、$C_b'$ の範囲を制限して

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f - \alpha_b \alpha_f \tag{26} \\
C_b' &= min \left( 1, \frac{\alpha_f (C_b + C_f) + \alpha_b (1 - \alpha_f) C_b}{\alpha} \right) \\
&= min \left( 1, \frac{\alpha C_b + \alpha_f C_f}{\alpha} \right) \\
&= min \left( 1, C_b + \frac{\alpha_f}{\alpha} C_f \right) \tag{27} \\
C &= \frac{\alpha_b C_b' + (1 - \alpha_b) \alpha_f C_f}{\alpha} \tag{28}
\end{align}
```

になります。

## 3.3. 後景が不透明のとき

$\alpha_b = 1$ (後景が不透明) のとき、どちらも $\alpha = 1$ が成り立ちます。

このとき「加算合成」の色は

```math
C = \alpha_f min(1, C_b + C_f) + (1 - \alpha_f) C_b \tag{29}
```

になり、「加算 (発光) 合成」の色は

```math
C = min(1, C_b + \alpha_f C_f) \tag{30}
```

になります。

後景が不透明の時は理論式 (14), (15) と一致することが分かります。

# 4. FireAlpaca での式 (推定)

FireAlpaca ver.2.4.4 で色を調べ、式を推定しました。

FireAlpaca は「加算合成」はないので「加算 (発光) 合成」のみになります。

## 4.1. 「加算 (発光) 合成」の式 (推定)

```math
\begin{align}
\alpha &= \alpha_b + \alpha_f - \alpha_b \alpha_f \tag{31} \\
C_b' &= min \left( 1, \alpha_f (C_b + C_f) + (1 - \alpha_f) C_b \right) \tag{32} \\
&= min ( 1, C_b + \alpha_f C_f ) \\
C_f' &= \frac{\alpha_b (1 -\alpha_f) C_b + \alpha_f C_f}{\alpha} \tag{33} \\
C &= \alpha_b \alpha C_b' + (1 - \alpha_b \alpha) C_f' \tag{34}
\end{align}
```

$C_b + C_f$ の範囲を制限せずに $C_b'$ の範囲を制限して、通常合成した色 $C_f'$ と $\alpha_b \alpha$ の割合で足した値になります。

## 4.2. 後景が不透明のとき

$\alpha_b = 1$ (後景が不透明) のとき、$\alpha = 1$ が成り立ちます。

このとき「加算 (発光) 合成」の色は

```math
C = min(1, C_b + \alpha_f C_f) \tag{35}
```

になり、理論式 (15) と一致します。