先日記載したコード、文字色の自動判定アルゴリズムに一部無駄があったので改良します。
【C#】背景色から黒文字か白文字の見やすい方を自動判定 (WCAG 2.0 利用版)
https://qiita.com/mainy/items/f5540f33d37d8ce6a46e
何が無駄かというと、白文字と背景色、黒文字と背景色を毎回計算して比較していました。
背景色の相対輝度の値から、白文字もしくは黒文字にズバッと判定できてもよさそうです。
数学的改良とカッコつけてますが、中学レベルです。
仕様を再確認
- 背景色の相対輝度を
x
とおく - 背景色の相対輝度と白文字の相対輝度の比率は
(1 + 0.05) / (x + 0.05)
- 背景色の相対輝度と黒文字の相対輝度の比率は
(x + 0.05) / (0 + 0.05)
つまり(1 + 0.05) / (x + 0.05) = (x + 0.05) / (0 + 0.05)
となる値は、ちょうど白文字と黒文字の分岐点となるわけです。
分岐点の値を先に計算しておけば、この値を基準に白文字か黒文字を判定させたほうが負荷が軽減されます。
数式で計算
分岐点の値をまずは計算します。
\frac{1 + 0.05}{x + 0.05} = \frac{x + 0.05}{0 + 0.05}
まずは簡単な数式に置き換えるため、y = (x + 0.05)
とおきます。
\frac{1.05}{y} = \frac{y}{0.05}
右辺と左辺を整理します。
y^2 = 1.05 \times 0.05
y = (x + 0.05)
を戻します。
\begin{align}
({x + 0.05})^2 &= 0.0525\\
x^2 + (2 \times 0.05 \times x) + 0.0025 &= 0.0525\\
x^2 + 0.1x -0.05 &= 0\\
\end{align}
2次方程式の解の公式に当てはめます。
\begin{align}
x &= \frac{-0.1 \pm \sqrt{0.1^2 - 4 \times 1 \times -0.05} }{2 \times 1}\\
x &= \frac{-0.1 \pm \sqrt{0.21} }{2}\\
x &= -0.05 \pm \frac{\sqrt{0.21}}{2}\\
\end{align}
近似値は以下の通りとなります。
\begin{align}
-0.05 + \frac{\sqrt{0.21}}{2} &\eqsim 0.17912878474779... \\
-0.05 - \frac{\sqrt{0.21}}{2} &\eqsim -0.27912878474779... \\
\end{align}
相対輝度の範囲は0~1です。つまり、値は必ず正の値になるので、
\begin{align}
x &= -0.05 + \frac{\sqrt{0.21}}{2}\\
x &\eqsim 0.17912878474779
\end{align}
計算した相対輝度が 0.17912878474779
以上であれば「黒文字」、未満であれば「白文字」の判定すれば良い事がわかります。
改良したコード
chooseTextColor() 関数の判定が以下の通りになります。
境界値がマジックナンバーになるので、ドキュメントにしっかりと境界値の意味を記載しておきましょう。
public static Color chooseTextColor(byte R, byte G, byte B)
{
// 背景色の相対輝度
double background = RelativeLuminance(R, G, B);
// 黒文字と白文字の判定に使う相対輝度境界値
const double border = 0.17912878474779D;
// 背景色の相対輝度が境界値以上なら黒文字、未満なら白文字
return background >= border ? Color.Black : Color.White;
}
おまけの数式計算
背景色と黒文字・白文字どちらかの相対輝度比率が 7.0
以上となるケースも、背景色の相対輝度から判断できそうです。
白文字のケース
相対輝度比率 が 7.0 以上になるためには、以下の不等式が成立すれば良さそうです。
7.0 \leqq \frac{1 + 0.05}{x + 0.05} \
サクッと計算します。
\begin{align}
7.0 &\leqq \frac{1 + 0.05}{x + 0.05} \\
7.0(x + 0.05) &\leqq 1.05 \\
7x + 0.35 &\leqq 1.05 \\
7x &\leqq 0.7 \\
x &\leqq 0.1 \\
\end{align}
相対輝度が 0.1 以下であれば、見やすい白文字の表記ができます。
黒文字のケース
相対輝度比率 が 7.0 以上になるためには、以下の不等式が成立すれば良さそうです。
7.0 \leqq \frac{x + 0.05}{0 + 0.05} \
サクッと計算します。
\begin{align}
7.0 &\leqq \frac{x + 0.05}{0 + 0.05} \\
7.0 \times 0.05 &\leqq x + 0.05 \\
0.35 - 0.05 &\leqq x \\
x &\geqq 0.3
\end{align}
相対輝度が 0.3 以上であれば、見やすい黒文字の表記ができます。
ちょっと見にくい文字の判定
上記の黒文字・白文字判定の範囲から単純に導き出せそうです。
背景色の相対輝度が以下の範囲の値だと、黒文字だろうが白文字だろうが、どちらを選んでも若干見にくい文字となります。
0.1 < x < 0.3 \
最後に
こんなコードで性能は求められないので、実際にはここまでする必要はないかと思います。
自己満足の世界です。