ペイントソフトのレイヤーモードを数式で眺める
ペイントソフトのレイヤーモードは、「乗算は暗くなる」「スクリーンは明るくなる」といった感覚的な言葉で解説されることが多く、具体的な計算方法まで紹介されることはあまりない。
それぞれの計算方法が分かれば、目的に合ったレイヤーモードをもっと選びやすくなると考えた。この記事では、普段使うレイヤーモードを数式で見て、各モードが画素にどのような計算をしているのかを整理する。
この記事で扱うモード
先に全体像を示しておく。モード名をクリックすると、それぞれの説明に移動できる。
| モード | 役割 |
|---|---|
| 通常 | 上の色をそのまま重ねる |
| 比較(暗) | チャンネルごとに暗い方を選ぶ |
| 乗算 | 色を掛けて暗くする |
| 焼き込みカラー | 暗くしながらコントラストを強める |
| 焼き込み(リニア) | 暗い方向へ直線的に変化させる |
| カラー比較(暗) | 色全体が暗い方を選ぶ |
| 比較(明) | チャンネルごとに明るい方を選ぶ |
| スクリーン | 反転して掛けて明るくする |
| 覆い焼きカラー | 明るくしながらコントラストを変える |
| 加算 | 色の値を足して明るくする |
| カラー比較(明) | 色全体が明るい方を選ぶ |
| オーバーレイ | 下の明暗で乗算とスクリーンを切り替える |
| ソフトライト | 明暗を穏やかに動かす |
| ハードライト | 上の明暗で乗算とスクリーンを切り替える |
| ビビッドライト | 焼き込みと覆い焼きを切り替える |
| リニアライト | 明るさを直線的に強く動かす |
| ピンライト | 比較(暗)と比較(明)を切り替える |
| ハードミックス | 各チャンネルをほぼ二値化する |
| 差の絶対値 | 上下の色の差を取り出す |
| 除外 | 差の絶対値より弱い差分を作る |
| 減算 | 上の色を下の色から引く |
| 除算 | 下の色を上の色で割る |
| 色相 | 上の色相だけを借りる |
| 彩度 | 上の彩度だけを借りる |
| カラー | 上の色相と彩度を借りる |
| 輝度 | 上の明るさだけを借りる |
レイヤーモードは「上下の色から新しい色を作る関数」
まず、完全に不透明な2枚のレイヤーを考える。下のレイヤーの色を下地、上のレイヤーの色を重ねる色と考えると分かりやすい。
レイヤーモードは、その2つの色を入力として、選んだルールで新しい色を作る。まずは記号を使わずに書くと、次のような流れである。
下の色 + 上の色 → レイヤーモードのルール → 新しい色
以降の式を短く書くために、この3つの色に名前を付ける。
| 記号 | 意味 |
|---|---|
C_base |
下のレイヤーの色。下地 |
C_top |
上のレイヤーの色 |
C_mode |
レイヤーモードが作った新しい色 |
すると、先ほどの流れは次の式になる。
C_mode = f(C_base, C_top)
f の中身を入れ替えたものが、乗算・スクリーン・差の絶対値などのレイヤーモードである。
RGBの各チャンネルを 0.0〜1.0 に正規化して考える。たとえば、赤チャンネルについて C_base = 0.3、C_top = 0.4 なら、乗算は次のようになる。
0.3 * 0.4 = 0.12
3つのチャンネルに同じ計算をすれば、RGBの結果になる。
まずは数値を入れてみる
下の色を C_base = 0.25、上の色を C_top = 0.4 とすると、代表的なモードはこうなる。
| モード | 計算 | 結果 |
|---|---|---|
| 乗算 | 0.25 * 0.4 |
0.10 |
| スクリーン | 1 - (1-0.25)(1-0.4) |
0.55 |
| オーバーレイ | 2 * 0.25 * 0.4 |
0.20 |
| 加算 | 0.25 + 0.4 |
0.65 |
この数字だけでも、乗算が暗くなり、スクリーンが明るくなる理由が見えてくる。
半透明のレイヤーでは、式の結果をさらに混ぜる
ここまでの説明は、主に上下の色が完全に不透明な場合のものである。実際のレイヤーには透明度があり、レイヤーモードは色の式を計算して終わりではない。
レイヤーモードを理解するとき、次の2段階に分けると分かりやすい。
- 上下の色から、モード固有の色
C_modeを作る C_modeを、上のレイヤーの不透明度や透明部分を使って下に重ねる
C_mode = f(C_base, C_top)
C_out = アルファ合成(C_base, C_top, C_mode)
ここで使う記号は次のとおりである。
| 記号 | 意味 |
|---|---|
C_out |
最終的に表示される色 |
a_base |
下のレイヤーのアルファ |
a_top |
上のレイヤーのアルファ |
p |
レイヤー設定の不透明度 |
m |
マスクなどによる追加の係数 |
上のレイヤーが実際に効く不透明度は、概念的には次になる。
a_top' = a_top * p * m
通常の合成では、出力の不透明度は次の式になる。
a_out = a_top' + (1 - a_top') * a_base
下のレイヤーが完全に不透明なら、色については次のように考えられる。
C_out = a_top' * C_mode + (1 - a_top') * C_base
下のレイヤーと上のレイヤーがどちらも完全に不透明なら、a_top' = 1 なので、最終的には C_mode だけが残る。だから普段は、乗算を C_base * C_top と説明できる。
一方、上のレイヤーが50%不透明なら、乗算で作った色をそのまま表示するのではなく、乗算結果と下の色の間を補間する。レイヤーの不透明度を下げると「乗算の濃さ」が変わるのはこのためである。
今回の画像
以下の例は、果物の写真を下地に、上半分が虹色・下半分がグレースケールのパターンを上のレイヤーとして重ねたものである。どちらも100%不透明なので、この例では最終出力 C_out は各モードが作る色 C_mode と同じになる。以降は各モードについて、下地・上のレイヤー・合成結果の順に並べて見る。
通常
上のレイヤーを、そのまま下に重ねるモードである。
C_mode = C_top
下のレイヤーが完全に不透明なら、上のレイヤーが100%不透明のときは上の色だけが見える。上が半透明なら、C_top と C_base の間になる。
「何もしない」ように見えるが、透明度を含めると、通常はレイヤー合成の基準になる大事なモードである。
比較(暗)
下と上の色をチャンネルごとに比較し、暗い方を選ぶ。
C_mode = min(C_base, C_top)
乗算と違って色を混ぜず、各チャンネルの小さい値を選ぶ。暗い線や影だけを残したいときに使われる。
乗算
C_mode = C_base * C_top
0.0〜1.0 の範囲なら、結果は必ず入力の小さい方以下になる。白 1.0 を掛けても相手の色がそのまま残り、黒 0.0 を掛けると黒になる。
この性質が、影・陰影・線画の色付けに向いている理由である。上のレイヤーに暗い色を置くほど、下の色を暗くする効果が強くなる。
例えば、下が 0.8、上が 0.5 なら、
0.8 * 0.5 = 0.4
となる。
焼き込みカラー
下の色を暗くしながら、コントラストも強めるモードである。
C_base = 1 のとき:
C_mode = 1
C_base < 1 かつ C_top = 0 のとき:
C_mode = 0
C_base < 1 かつ C_top > 0 のとき:
C_mode = 1 - min(1, (1-C_base) / C_top)
結果は通常 0.0〜1.0 に収める。上の色が黒に近づくほど、下の色が急激に暗くなる。
焼き込み(リニア)
C_mode = max(0, C_base + C_top - 1)
2つの色を足してから 1 を引くので、暗い方向へ直線的に変化する。減算と似て見えるが、式は異なる。
カラー比較(暗)
比較(暗)はチャンネルごとに比較するが、カラー比較(暗)は色全体の明るさを比較して、下か上のどちらか一方の色を選ぶ。
sum(C_base) < sum(C_top) のとき:
C_mode = C_base
sum(C_base) >= sum(C_top) のとき:
C_mode = C_top
ここで sum(C) は、RGB各チャンネルの値を足したものとする。そのため、比較(暗)のようにチャンネルごとに別々の色を組み合わせることはない。
比較(明)
下と上の色をチャンネルごとに比較し、明るい方を選ぶ。
C_mode = max(C_base, C_top)
黒 0.0 はほとんど何もせず、白 1.0 はそのチャンネルを白にする。明るい線や光だけを重ねたいときに使える。
スクリーン
C_mode = 1 - (1 - C_base) * (1 - C_top)
展開すると、
C_mode = C_base + C_top - C_base * C_top
とも書ける。
黒 0 を入れると、
1 - (1 - C_base) * (1 - 0) = C_base
なので黒はほとんど何もしない。白 1 を入れると、結果は 1 になる。乗算とは逆に、白い部分ほど下の色を明るくする。光・ハイライト・発光表現に向いているのは、この性質による。
覆い焼きカラー
下の色を明るくしながら、コントラストを変えるモードである。
C_base = 0 のとき:
C_mode = 0
C_base > 0 かつ C_top = 1 のとき:
C_mode = 1
C_base > 0 かつ C_top < 1 のとき:
C_mode = min(1, C_base / (1-C_top))
上の色が白に近づくほど、下の色が急激に明るくなる。強い光や発光の芯を作るのに向いているが、明るさが極端になりやすい。
加算
C_mode = C_base + C_top
2つの色の光量を、そのまま足すと考えるモードである。明るい色同士を重ねると、すぐに白に近づく。
表示できる範囲に収める場合は、一般に次のようになる。
C_mode = min(1, C_base + C_top)
ソフトによっては別の名前で呼ばれることもあるが、同じ系統のモードとして扱われることが多い。
カラー比較(明)
カラー比較(暗)の反対で、色全体の明るさが大きいほうを選ぶ。
sum(C_base) > sum(C_top) のとき:
C_mode = C_base
sum(C_base) <= sum(C_top) のとき:
C_mode = C_top
比較(暗)と比較(明)の違いと同じように、チャンネル単位の比較ではなく、色全体の比較である。
オーバーレイ
オーバーレイは、下の色が暗いか明るいかで、乗算寄りかスクリーン寄りかを切り替える。
C_base < 0.5 のとき:
C_mode = 2 * C_base * C_top
C_base >= 0.5 のとき:
C_mode = 1 - 2 * (1-C_base) * (1-C_top)
暗い下地では乗算のように暗くなり、明るい下地ではスクリーンのように明るくなる。中間の 0.5 付近を基準にコントラストを強める、と考えるとよい。
例えば C_base = 0.75、C_top = 0.4 なら、下の色が明るいのでスクリーン側を使う。
1 - 2 * (1-0.75) * (1-0.4) = 0.70
ソフトライト
ソフトライトは、上の色に応じて、下の色を暗くしたり明るくしたりするモードである。オーバーレイよりも変化が穏やかになりやすい。
代表的な式の一つは次のように書ける。
x <= 0.25 のとき:
g(x) = ((16*x - 12)*x + 4)*x
x > 0.25 のとき:
g(x) = sqrt(x)
C_top <= 0.5 のとき:
C_mode = C_base - (1 - 2*C_top) * C_base * (1-C_base)
C_top > 0.5 のとき:
C_mode = C_base + (2*C_top - 1) * (g(C_base)-C_base)
式は少し長いが、見方は単純である。上の色が50%グレーより暗ければ下を暗くし、明るければ下を明るくする。
ハードライト
オーバーレイと似ているが、明るいか暗いかを上の色で判断する。
C_top < 0.5 のとき:
C_mode = 2 * C_base * C_top
C_top >= 0.5 のとき:
C_mode = 1 - 2 * (1-C_base) * (1-C_top)
オーバーレイが「下の画像に光を当てる」感じなら、ハードライトは「上のレイヤーから強い光を当てる」感じである。
ビビッドライト
上の色が暗いか明るいかで、焼き込みカラーと覆い焼きカラーを切り替える。
C_top < 0.5 のとき:
C_mode = 焼き込みカラー(C_base, 2*C_top)
C_top >= 0.5 のとき:
C_mode = 覆い焼きカラー(C_base, 2*(C_top-0.5))
コントラストの変化が強く、扱いも難しい。強い陰影や極端な光を作るためのモードと考えるとよい。
リニアライト
C_mode = clamp(C_base + 2*C_top - 1, 0, 1)
上の色を2倍してから下の色に加える。50%グレーを基準に、明るい部分は明るく、暗い部分は暗くする。
ピンライト
上の色に応じて、比較(暗)または比較(明)に近い処理を切り替える。
C_top < 0.5 のとき:
C_mode = min(C_base, 2*C_top)
C_top >= 0.5 のとき:
C_mode = max(C_base, 2*C_top - 1)
オーバーレイやソフトライトよりも、色の置き換わりが目立ちやすい。
ハードミックス
C_base + C_top < 1 のとき:
C_mode = 0
C_base + C_top >= 1 のとき:
C_mode = 1
各チャンネルの結果を0か1に丸めるため、画像がほとんど二値化される。通常の塗りや調整より、ポスターのような極端な効果に向いている。
差の絶対値
C_mode = abs(C_base - C_top)
下と上の色の差を、絶対値にして取り出す。順番を入れ替えても結果は同じである。
同じ色同士なら、
abs(C_base - C_base) = 0
なので黒になる。白 1.0 を重ねると、
abs(C_base - 1) = 1 - C_base
となり、色が反転する。2枚の画像の位置合わせや差分の確認に便利なモードである。
除外
差の絶対値に似ているが、コントラストを弱めたような結果になる。
C_mode = C_base + C_top - 2 * C_base * C_top
黒 0 では変化せず、白 1 では色が反転する。中間の色では差の絶対値ほど強い差になりにくい。
減算
C_mode = max(0, C_base - C_top)
上の色を下の色から引くモードである。焼き込み(リニア)と似て見えるが、減算は単純に C_base - C_top を計算する。
除算
C_mode = min(1, C_base / C_top)
下の色を上の色で割る。C_top = 0 では式が定義できず、0 に近いと結果が急激に大きくなるため、実際のソフトでは特別な扱いが入る。この例の画像では、ゼロで割るチャンネルは白 1 としている。
色相
色相は、上のレイヤーから色相だけを借り、下のレイヤーの彩度と明るさを残す。
色を色相 H、彩度 S、明るさ L の3つに分けて考えると、概念的には次のようになる。
C_mode = HSL(H_top, S_base, L_base)
RGBの赤・緑・青を直接掛けたり足したりするモードではない。「色味だけを変えたい」ときに使う。
彩度
上のレイヤーから彩度だけを借り、下のレイヤーの色相と明るさを残す。
C_mode = HSL(H_base, S_top, L_base)
彩度の低い上の色を使うと、下の色を鮮やかさの少ない方向へ動かせる。
カラー
上のレイヤーの色相と彩度を使い、下のレイヤーの明るさを残す。
C_mode = HSL(H_top, S_top, L_base)
モノクロ画像に色を付けたり、線画や陰影の明るさを保ったまま着色したりするときに便利である。
輝度
下のレイヤーの色相と彩度を残し、上のレイヤーの明るさを使う。
C_mode = HSL(H_base, S_base, L_top)
カラーの反対側の使い方で、色味を保ったまま明るさだけを変えたいときに使える。