HSL 色空間#
HSL 色空間は
Hue (色相)
Saturation (彩度)
Lightness (明度)
により色を表現する [1]。
HSL 色空間は Joblove and Greenberg[2] が定義したものであり、 次のように HSL 色空間による表現 \((h, s, l)\) から RGB 色空間による表現 \((r, g, b)\) を計算する。
\[\begin{align*}
r' &= \begin{cases}
1 & \text{if $0 \le h \le 1/6$ or $5/6 \le h < 1$} \\
2 - 6h & \text{if $1/6 \le h \le 2/6$} \\
0 & \text{if $2/6 \le h \le 4/6$} \\
6h - 4 & \text{if $4/6 \le h \le 5/6$}
\end{cases}
\\
g' &= \begin{cases}
6h & \text{if $0 \le h \le 1/6$} \\
1 & \text{if $1/6 \le h \le 3/6$} \\
4 - 6h & \text{if $3/6 \le h \le 4/6$} \\
0 & \text{if $4/6 \le h < 1$}
\end{cases}
\\
b' &= \begin{cases}
0 & \text{if $0 \le h \le 2/6$} \\
6h - 2 & \text{if $2/6 \le h \le 3/6$} \\
1 & \text{if $3/6 \le h \le 5/6$} \\
6 - 6h & \text{if $5/6 \le h < 1$}
\end{cases}
\\
\begin{pmatrix} r \\ g \\ b \end{pmatrix} &=
\begin{cases}
\left(
\begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
+ s \left(
\begin{pmatrix} r' \\ g' \\ b' \end{pmatrix}
- \begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
\right)
\right) \cdot 2i
& \text{if $i \le 1/2$}
\\
\begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
+ s \left(
\begin{pmatrix} r' \\ g' \\ b' \end{pmatrix}
- \begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
\right)
+ \left(
\begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
- s \left(
\begin{pmatrix} r' \\ g' \\ b' \end{pmatrix}
- \begin{pmatrix} 0.5 \\ 0.5 \\ 0.5 \end{pmatrix}
\right)
\right) (2i - 1)
& \text{if $i \ge 1/2$}
\end{cases}
\end{align*}\]
Note
Joblove and Greenberg[2] の定式化では最後が \((2i - 1)\) でなく \((2 - 2i)\) だったが、 論文中の記述と矛盾するため \((2i - 1)\) とした。
HSL から RGB への変換については、 CSS Color Module Level 4[3] に JavaScript による実装例があるが、 ここでは、Python で実装して挙動を確認する。
色相に対する RGB の変化#
まず、\((r', g', b')\) の計算式を実装する。
%%cython
cpdef double hue2r(double hue):
"""色相に対する RGB の R を計算する
hue は [0, 1] の範囲にあるとする。
"""
if (0.0 <= hue <= 1.0 / 6.0) or (5.0 / 6.0 <= hue):
return 1.0
elif 1.0 / 6.0 <= hue <= 2.0 / 6.0:
return 2.0 - 6.0 * hue
elif 2.0 / 6.0 <= hue <= 4.0 / 6.0:
return 0.0
else:
return 6.0 * hue - 4.0
cpdef double hue2g(double hue):
"""色相に対する RGB の G を計算する
hue は [0, 1] の範囲にあるとする。
"""
if 0.0 <= hue <= 1.0 / 6.0:
return 6 * hue
elif 1.0 / 6.0 <= hue <= 3.0 / 6.0:
return 1.0
elif 3.0 / 6.0 <= hue <= 4.0 / 6.0:
return 4.0 - 6.0 * hue
else:
return 0.0
cpdef double hue2b(double hue):
"""色相に対する RGB の B を計算する
hue は [0, 1] の範囲にあるとする。
"""
if 0.0 <= hue <= 2.0 / 6.0:
return 0.0
elif 2.0 / 6.0 <= hue <= 3.0 / 6.0:
return 6.0 * hue - 2.0
elif 3.0 / 6.0 <= hue <= 5.0 / 6.0:
return 1.0
else:
return 6.0 - 6.0 * hue
これを用いて、色相に対する \((r', g', b')\) の挙動を以下に示す。
色相、彩度、明度に対する色の変化#
続いて、彩度と明度も含めた色の計算を行う。
Caution
アニメーションのバーを速く動かすと簡単に表示が崩れてしまう。