RGBをHSLに変換
RGB→HSL変換は、3つの色チャンネルを角度・彩度・輝度として記述し直します。重要なのは最大チャンネルと最小チャンネルだけです。その2つの中点が輝度、その差がクロマであり、どちらが最大かで色相が属する60°のセクターが決まります。セクター内における中間チャンネルの位置から、正確な角度が求まります。
左側に色を入力してください。# の有無を問わない16進数の値、 rgb(), hsl(), oklch() および CSS の色名に対応しています。
RGBをHSLに変換はどう動きますか?
変換のすべては、最大チャンネルと最小チャンネルという2つの数で決まります。3つのチャンネルを0–1にスケールすると、輝度はその2つの中点、クロマはその距離です。クロマがゼロなら3チャンネルは等しく、色はグレーであり、計算すべき色相はありません。
どのチャンネルが最大かがセクターを決めます
色相環は6つの60°セクターに分かれます。赤が最大ならマゼンタから黄までのセクター、緑が最大なら黄からシアンまで、青が最大ならシアンからマゼンタまでに入ります。正確にどこに落ちるかは、中間のチャンネルで決まります。赤が最大の場合、角度は((G − B) / chroma) × 60で、他の2つは同じ式に2または4セクターのオフセットを加えたものです。
この式は負になることがあります(赤が支配的な色で、青が緑を上回る場合です)。だからこそ、正しい実装はすべて、360を加えて剰余を取ります。この処理を省いた実装は、全色のおよそ6分の1で負の色相を返し、下流で何かが色相でソートを試みるまで、バグは見えません。
彩度は『あり得る最大値』を基準に測られます
彩度は生のクロマではありません。クロマを、輝度が許す最大のクロマで割ったものです。その最大値は1 − |2L − 1|です。分母は両端でゼロに近づくため、チャンネル差がわずかな、黒に近い色や白に近い色は、高い彩度として報告されます。これは正しいのですが、大半の人がこの数値に期待する意味とは異なります。
HSLが得意なこと、そうでないこと
人間にとっては優れた表記です。「同じ色で彩度を下げる」「同じ色で少し暗くする」は、HSLでは1つの数値の変更で済み、RGBでは3つの数値の変更になります。また、色相スライダーは極座標的な空間でなければ、そもそも成立しません。これは実在する利点であり、HSLが生き残ってきた理由です。
計算の基礎としては不適切です。HSLの輝度軸は3チャンネルを等しく重み付けしますが、人間の視覚は緑を青の約10倍重く見るため、同じ輝度の数値が同じ明るさに見えるとは限りません。HSLを前提に構築したカラースケール、混合、コントラストの判断は、すべてこの誤差を受け継ぎます。OKLCHは同じ構造の表記——角度・クロマ・輝度——でありながら、目の知覚に合った軸を持ち、下の出力にも表示されています。
RGBチャンネル
rgb(255 136 0)
色相・彩度・輝度
hsl(32 100% 50%) max = 255 (red) → 1.000 min = 0 (blue) → 0.000 chroma = 1.000 lightness = (1.000 + 0.000) / 2 = 50% hue = ((0.533 − 0.000) / 1.000) × 60 = 32°
RGBをHSLに変換が対応するオプションとエッジケースは?
| パラメータ | 型 | デフォルト | 動作とエッジケース |
|---|---|---|---|
| max, min | 0–1 | — | スケール後の3つのチャネルの最大値と最小値です。残りはすべてこの2つから求められます。 |
| クロマ | max − min | — | 色が灰色からどれだけ離れているかを表します。0なら灰色であり、このとき色相は未定義です。 |
| 明度 | (max + min) / 2 | — | 中間値です。どのチャネルが最大・最小かは無視される点に注意してください。HSLの知覚上の問題はここに起因します。 |
| 彩度 | chroma / (1 − |2L − 1|) | — | その明度で利用できる最大値に対するクロマの比率であり、絶対的な尺度ではありません。 |
| 色相(赤が最大) | ((G − B) / C) × 60 | — | B > Gのときは負になることがあります。360を足して剰余を取ってください。 |
| 色相(緑が最大) | ((B − R) / C + 2) × 60 | — | 同じ式を2セクターずらしたものです。 |
| 色相(青が最大) | ((R − G) / C + 4) × 60 | — | 4セクターずらしたものです。 |
| グレー | C = 0 | 色相0 | 3つの同じ数値から計算で導かれる値ではなく、0として報告されます。 |
よくある質問
RGBからHSLへの変換はどうやりますか?
各チャンネルを255で割ります。最大値と最小値を取り、輝度はその中点、クロマはその差です。クロマがゼロなら色はグレーで、終わりです。そうでなければ、彩度はchroma / (1 − |2L − 1|)であり、色相はどのチャンネルが最大かに応じて決まります。赤なら((G − B) / chroma) × 60、緑なら((B − R) / chroma + 2) × 60、青なら((R − G) / chroma + 4) × 60です。結果が負になったら、360を足して剰余を取ります。
色相が負の値になるのはなぜですか?
赤が最大の分岐は緑から青を引くため、2つのうち青のほうが大きいと、結果はゼロ未満になります。修正方法は、正しい実装が必ず持っている剰余演算です。360を足して剰余を取ります。影響を受けるのは色空間のおよそ6分の1——赤のマゼンタ側——で、通常は何かが色相でソートや補間を試みるまで気づかれません。
HSLの彩度は実際には何を測っているのですか?
クロマそのものではなく、輝度が保持しうる最大のクロマに対する割合です。だからこそ、rgb(2 0 0)——ほぼ黒——は100%の彩度を報告します。輝度0.4%で可能な範囲では、これ以上ないほど彩りが強いのです。色の鮮やかさの絶対的な尺度が欲しい場合、それがOKLChのクロマです。
CSSではRGBよりHSLのほうが良いですか?
手で編集するなら、しばしばそうです。彩度を下げたり暗くしたりするのが3つの数値ではなく1つの数値で済み、色相は思考の対象にできるからです。一方、生成されるもの——カラースケール、グラデーション、補間された状態——には、見た目以上に不向きです。HSLの輝度は知覚的なものではなく、等間隔の数値が等間隔の色になるとは限らないためです。人が入力する場所ではHSLを、プログラムが計算する場所ではOKLCHを使ってください。
変換で何か失われますか?
数学的には失われません。HSLとRGBはまったく同じ色の集合を記述し、対応関係は可逆です。失われるのは、結果の書き表し方における精度です。整数の色相と小数第1位までのパーセントでは、sRGBの約1,670万通りの値をすべて区別できず、2つの異なる色が同じHSLとして表示されることがあります。ここの値は、往復できる十分な桁数を持っています。
まったく異なる2つの色が、同じ色相を報告するのはなぜですか?
色相は色の方向だけを記録し、その量を記録しないためです。rgb(255 0 0)とrgb(40 30 30)はどちらも色相0に位置し、彩度と輝度だけが完全に異なります。この分離こそがHSLの狙いです。どの色かを1軸で、どれだけ強く、どれだけ明るいかを2軸で表します。ほぼグレーの色が、それらしい色相を報告できる理由でもあります。