CSS カラー HDR モジュール レベル 1

W3C 最初の公開作業草案

この文書の詳細情報
このバージョン:
https://www.w3.org/TR/2026/WD-css-color-hdr-1-20260624/
最新公開バージョン:
https://www.w3.org/TR/css-color-hdr-1/
編集者草案:
https://drafts.csswg.org/css-color-hdr-1/
以前のバージョン:
履歴:
https://www.w3.org/standards/history/css-color-hdr-1/
フィードバック:
CSSWG イシューレポジトリ
仕様内インライン
編集者:
Chris Lilley (W3C)
この仕様に編集提案:
GitHub エディター
テストスイート:
https://wpt.fyi/results/css/css-color-hdr/

要約

このモジュールは、高ダイナミックレンジ(HDR)を有効にするために、CSS Color 4および5への追加機能を定義します。

CSSは、構造化文書(HTMLやXMLなど)の 画面や紙などでのレンダリング方法を記述するための言語です。

この文書のステータス

このセクションでは、本書が公開された時点でのステータスを説明します。 現在のW3C出版物の一覧およびこの技術レポートの最新版は W3C標準およびドラフトのインデックスで参照できます。

この文書は、CSSワーキンググループ により 作業草案として 勧告プロセスに基づき公開されました。 作業草案としての公開は、 W3Cおよびその会員による支持を意味するものではありません。

これはドラフト文書であり、 今後更新・置き換え・廃止される場合があります。 進行中の作業以外としてこの文書を引用することは不適切です。

ご意見は GitHubでイシューを提出(推奨)の形で 「css-color-hdr」仕様コードをタイトルに含めて送信してください(例: “[css-color-hdr] …コメント要約…”)。 すべてのイシューとコメントは アーカイブされています。 または、パブリックメーリングリスト (アーカイブwww-style@w3.org へのメールでも受け付けています。

この文書は 2025年8月18日付W3Cプロセス文書 に従って管理されています。

この文書は、W3C特許ポリシー の下で運用されているグループによって作成されました。 W3Cは、グループの成果物に関連してなされた特許開示の公開リストを保持しており、 そこに特許開示の手順も記載されています。 個人が本当に特許に関する知識を有し、その特許が 必須クレーム を含むと考える場合には、 W3C特許ポリシー第6節 に従い、その情報を開示する必要があります。

1. はじめに

このセクションは規範的ではありません。

CSS Color 4 は、オープンウェブプラットフォームにワイドカラ―ガマット(WCG)カラースペースを追加します。 設計上、これらはすべて標準ダイナミックレンジ(SDR)カラースペースです。 この仕様は、ハイダイナミックレンジ(HDR)をサポートするための追加機能を定義します。

4つのカラースペースのエレクトロオプティカルトランスファ関数(EOTF): 拡張sRGBおよびリニアライトsRGB (CSS Color 4で定義)、および 本仕様で定義されるパーセプチュアルクォンタイザー(PQ)とハイブリッドログガンマ(HLG)、 出典:[Rec_BT.2100]

WCG仕様は数十年にわたり概ね安定していますが、 HDR規格はまだ発展途上であり、 過去10年の間に頻繁に改訂されています。

1.1. 値の定義

この仕様は、CSSプロパティ定義の規約に従う。これは、[CSS2]に由来し、 値定義構文[CSS-VALUES-3]から用いる。 この仕様で定義されていない値型は、CSS Values & Units [CSS-VALUES-3]で定義されている。 他のCSSモジュールとの組み合わせにより、これらの値型の定義が拡張されることがある。

各定義に列挙されているプロパティ固有の値に加えて、 この仕様で定義されるすべてのプロパティは、 プロパティ値としてCSS全体キーワードも受け付ける。 可読性のため、それらは明示的には繰り返していない。

2. HDR用語集

2.1. ダイナミックレンジの定義

ピーク輝度は、表示可能な最も明るい白の輝度である。 これは線形光量であり、 cd/m2で測定され、nitsとも呼ばれる。

最深黒は、表示可能な最も暗い黒の輝度である。 これは視聴時のフレア (画面で反射される環境光)の影響を受けるため、 実際の値は視聴条件に依存する。

線形ダイナミックレンジ は、表示可能な最も明るい色と最も暗い色との間の 輝度比である。

ダイナミックレンジは、 線形 ダイナミックレンジの2を底とする対数である。 これは、私たちの目が明るさを対数スケールで知覚するためである。 ダイナミックレンジは写真のストップで測定される。 1ストップは輝度が2倍になることを表す。

function DynamicRange (peak, deepest) {
  return Math.log2(peak) - Math.log2(deepest);
  } 

HDR基準白は、 メディア白または拡散白とも呼ばれ、 [Rpt_BT.2408-9] の2.1節で定義され、 標準値は203 cd/m2である。 これは通常の白い背景の色、 または暗い背景上の白いテキストの色である。 画面全体にわたって快適に視聴できる。

標準ダイナミック レンジ(SDR)では、 HDR基準白はまた、 フル強度の赤、緑、青によって生成される 最も明るい可能な色でもある。

例えば、sRGBでは、 標準的な視聴条件の下で、 白は80 cd/m²の輝度を持つように定義され、 黒は0.2 cd/m²の輝度を持つように定義されている。 したがって、ダイナミックレンジは8.6ストップである。

ユーザーの好みや標準条件とは異なる視聴条件に合わせるため、 画面全体の明るさを調整することは一般的である。

SDRでは、画面を明るくしてもダイナミックレンジは変わらない。 なぜなら、最も暗い色も明るくなるためである。

例えば、sRGB画面は、 白の輝度が160 cd/m²になるように設定されることがあり、 その場合、最深黒の輝度は0.4 cd/m²になる。 ダイナミックレンジは依然として8.6ストップである。

高ダイナミックレンジ (HDR)では、 HDR基準白より明るい色を表示できる。 例えば、HDRディスプレイ上のHDR基準白が203 cd/m²に設定されている場合、 小さなハイライトを1000 cd/m²で表示できることがある。 通常、最も明るい色は、 ディスプレイの小さな部分でのみ、 かつ限られた時間だけ表示できる。 これはエネルギー使用量と発熱上の考慮による。

例えば、HDR基準マスタリングディスプレイでは、 小面積のピーク白の輝度が1000 cd/m²である一方、 最深黒の輝度は0.05 cd/m²である場合がある。 したがって、ダイナミックレンジは14.3ストップである。

HDRでは、より明るい画面を用いるとダイナミックレンジが増加し、 HDR基準白の輝度は一定のままである。

例えば、[Rec_BT.2100]で定義される rec2100-pq色空間を使用すると、 最も明るいピーク白は10,000 cd/m²の輝度を持つように定義され、 最深黒は0.001 cd/m²の輝度を持つ。 したがって、符号化されたダイナミックレンジは23.3ストップである。

SDR とHDRのダイナミックレンジを対数スケールで示す図を追加する

§ 9 SDRとHDRコンテンツの合成を行う場合、 および色空間変換では、 SDRコンテンツのHDR基準白は 203 cd/m² [Rpt_BT.2408-9] に固定されるべきである。 これにより、合成への入力のHDR基準白レベルが、 結合された信号のHDR基準白レベルに到達するようになる。

HDR(またはSDRとHDRが混在した)コンテンツを表示する場合、 基準マスタリングディスプレイより能力の低いディスプレイや、 標準条件とは異なる視聴条件では、 色の再レンダリング ステップ(OOTF)が実行される。 これにより、HDR基準白が203 cd/m²より低い値または高い値で表示される場合がある。

2.2. ヘッドルームの導入

HDRディスプレイが生成できるピーク輝度レベルは、 大きく異なる。

ピーク輝度がHDR基準白を上回る量は、 線形HDR ヘッドルームと呼ばれ、 その値はHDR基準白のレベル、 ユーザーの好み、 および視聴条件に依存する。

例えば、あるディスプレイが HDR基準白を160 cd/m2で表示し、 ピーク輝度が1000 cd/m2である場合、 そのディスプレイは1000 / 160 = 6.25倍の線形 HDRヘッドルームを持つ。

HDRヘッドルームは、 線形 HDRヘッドルームの2を底とする対数であり、 ダイナミックレンジと同様に 写真のストップで表される。

function Headroom (peak, reference) {
  return Math.log2(peak) - Math.log2(reference);
  } 
例えば、あるディスプレイが HDR基準白を160 cd/m2で表示し、 ピーク輝度が1000 cd/m2である場合、 そのディスプレイはlog2(1000) - log2(160) = 2.64ストップのHDRヘッドルーム を持つ。

したがって、標準 ダイナミックレンジ(SDR)は、 定義上、0ストップのHDR ヘッドルームを持つ。 なぜなら、最も明るい白がHDR基準白と同じであるためである。

例えば、低価格帯のHDRディスプレイ (DisplayHDR 400、 Vesa Certified DisplayHDR適合性の最下位ティア[DisplayHDR]の 要件をちょうど満たすもの)は、 HDR基準白を最大200 cd/m2で表示する一方、 ピーク白はわずか400 cd/m2である場合がある (最も明るいHDR基準白では、HDRヘッドルームは1ストップのみ)。
例えば、高性能なHDRディスプレイ (DisplayHDR 1400、 Vesa Certified DisplayHDR適合性の現在の最上位ティアの要件を上回るもの)は、 HDR基準白を最大400 cd/m2で表示する一方、 そのピーク白は1600 cd/m2である場合がある。

暗い視聴条件で、 HDR基準白を100 cd/m2に設定すると、 これは4ストップのHDRヘッドルーム (16倍の線形HDRヘッドルーム)を与える。

Webプラットフォームは現在、 ディスプレイのヘッドルームのレベルを直接公開していない。 これは、それが視聴条件に依存し、 リアルタイムで量子化されていないヘッドルーム情報は 追跡ベクトルになり得るためである (例えば、ユーザーが屋外へ移動し、 晴天であることを検出する場合)。

利用可能な最大レベルの HDRヘッドルームを使用することが、 常に望ましいとは限らない。 CSSは、大まかな意味で、 どの程度のヘッドルームが望ましいかを制御する方法を提供し、 このレベルは要素ごとに、 また時間とともに変化し得る。

例えば、写真のグリッドを表示するWebページを考える。 その中にはHDRのものがあり、 太陽を直接撮影した写真のような非常に高いダイナミックレンジの画像も含まれる。 これらの写真の集合を フルダイナミックレンジで一緒に見るのは疲れるだろう。 同時に、 すべてをSDR範囲に押し込めると、 個々の写真の特性を十分に表現できない。 設計上の目標は、写真群を意味のある形で評価できるように、 「十分な」HDRを示すことである。

3. ダイナミックレンジの制御

3.1. dynamic-range-limit プロパティ

名前: dynamic-range-limit
値: standard | no-limit | constrained | <dynamic-range-limit-mix()>
初期値: no-limit
適用対象: すべての要素
継承: はい
パーセンテージ: 該当なし
算出値: dynamic-range-limit の算出値を参照
正規順序: 文法通り
アニメーション型: dynamic-range-limit-mix()による
テスト
standard
表示される最高輝度の色は、 HDR基準白、すなわちCSS色whiteと同じである。
no-limit
表示される最高ピーク輝度は、 HDR基準白、すなわちCSS色whiteよりもはるかに大きい。 正確なレベルは指定されない。
constrained
表示される最高ピーク輝度は、 HDR基準白、すなわちCSS色whiteよりもいくらか大きく、 SDRコンテンツとHDRコンテンツの混在を 快適に一緒に視聴できるようにする。
body { dynamic-range-limit: standard; }
div.photogrid img { dynamic-range-limit: constrained }

3.2. ダイナミックレンジ制限のミックス:dynamic-range-limit-mix()関数

この関数は1つ以上のdynamic-range-limit値を受け取り、 それらを内部的にHDR基準白からのストップ値へ変換し、 指定の比率でミックスした結果にディスプレイを調整します。 プライバシー保護のため、実際の計算結果は外部には公開されません。

dynamic-range-limit-mix() = dynamic-range-limit-mix( [ <'dynamic-range-limit'> && <percentage [0,100]> ]#{2,} )
テスト

3.3. dynamic-range-limit の算出値

指定値がstandardconstrained、またはno-limitである場合、算出値は指定値と同一です。

指定値がdynamic-range-limit-mix()の場合、算出値は以下のアルゴリズムで決定されます。

  1. 混合するパラメータの算出値を v1vN とする。

  2. 混合比率(パーセンテージ)を p1pN とし、合計が100%になるよう正規化する。

  3. 寄与率を次のように定義する:

    • v1vNstandard であるもののパーセンテージを p1_standardpN_standard とする。

    • v1vNconstrained であるもののパーセンテージを p1_constrained_highpN_constrained_high とする。

    • v1vNno-limit であるもののパーセンテージを p1_no_limitpN_no_limit とする。

  4. 重み付き合計を次のように計算する:

    • p_standard = (p1_standard*p1+...+pN_standard*pN)/100

    • p_constrained_high = (p1_constrained_high*p1+...+pN_constrained_high*pN)/100

    • p_no_limit = (p1_no_limit*p1+...+pN_no_limit*pN)/100

  5. p_standardp_constrained_high、またはp_no_limitのいずれかが100%の場合、算出値はそれぞれstandardconstrainedno-limit となる。

  6. それ以外の場合、算出値はdynamic-range-limit-mix() となり、パラメータは standardconstrainedno-limit(この順)、および割合 p_standardp_constrained_highp_no_limitとなり、割合が0%のものは省略する。すべてのパラメータが省略される場合、算出値は初期値となる。

テスト
次の
dynamic-range-limit-mix(
    high 10%,
    dynamic-range-limit-mix(standard 25%, constrained 75%) 20%,
    dynamic-range-limit-mix(constrained 10%, no-limit 30%) 20%)
の算出値は
dynamic-range-limit-mix(standard 10%, constrained 40%, no-limit 50%)

4. <color> 構文

このモジュールは <color-function> 型を拡張します:

<color-function> = <rgb()> | <rgba()> |
    <hsl()> | <hsla()> | <hwb()> |
    <lab()> | <lch()> | <oklab()> | <oklch()> |
    <ictcp()> | <jzazbz()> | <jzczhz()> |
    <alpha()> |
    <color()> |
    <hdr-color()>
ictcp() = ictcp([from <color>]?
  [<percentage> | <number> | none]
  [<percentage> | <number> | none]
  [<percentage> | <number> | none]
  [ / [<alpha-value> | none] ]? )
jzazbz() = jzazbz([from <color>]?
  [<percentage> | <number> | none]
  [<percentage> | <number> | none]
  [<percentage> | <number> | none]
  [ / [<alpha-value> | none] ]? )
jzczhz() = jzczhz([from <color>]?
  [<percentage> | <number> | none]
  [<percentage> | <number> | none]
  [<hue> | none]
  [ / [<alpha-value> | none] ]? )

5. HDR色のヘッドルームによるパラメータ化: hdr-color() 関数

hdr-color() 関数は、HDRヘッドルームに基づいて自動的に値が計算される色の範囲を指定できます。

これは、2つの<color>値を、 それぞれHDRヘッドルームのレベルとともに指定することで実現します。 (2つのヘッドルーム値は異なる必要があります)。 実際の値は、現在のHDRヘッドルーム量に基づいて これら2つの色の間を補間して計算されます。 詳細は § 5.1 ヘッドルームに基づく色の補間 で説明します。

これは、 [ISO_21496-1] に準拠したラスター画像の ゲインマップや、 [SMPTE-ST-2094-50] のアダプティブゲインカーブに 類似した仕組みです。

プライバシー保護のため、実際に計算された色や 実際のHDRヘッドルームの値は公開されません。 これはフィンガープリント防止のためです。

その構文は次の通りです:

hdr-color() = color-hdr([ <color> && <number [0,∞]>? ]#{2})
次の色を考える:
color-hdr(
  color(rec2100-linear 0.9 1.0 0.8) 0,
  color(rec2100-linear 1.8 2.0 1.5) 2);

HDR ヘッドルームが <= 0 のディスプレイ、 言い換えればSDRディスプレイでは、 この色は次のように表示される

color(rec2100-linear 0.9 1.0 0.8)

HDR ヘッドルームが >= 2 のディスプレイでは、 この色は次のように表示される

color(rec2100-linear 1.8 2.0 1.5) 2);

ヘッドルームが0から2の間にあるディスプレイでは、色は 補間される。として、 HDRヘッドルームが1のディスプレイでは:

X = 243.664, Y = 275.713, Z = 244.000

色は絶対D65 CIE XYZで補間される。

これは、xyz-d65から導出される。 各色成分に203 [Rpt_BT.2408-9] を掛けることで、相対単位(白のYは実際の明るさに関係なく1)から cd/m²の絶対単位、別名「nits」へ変換する。 サンプルコードでは、 この定数はYw、 すなわちHDR基準白の輝度として表される。

例えば、css色white
color(xyz-d65 0.9505 1 1.089)

絶対D65 XYXでは、これは [192.9426, 203, 221.0787]である

5.1. ヘッドルームに基づく色の補間

ヘッドルーム H1 の色 c1 とヘッドルーム H2 の色 c2 を ヘッドルーム H で補間し、結果カラ cxyz を得るには、

  1. c1xyzc1絶対D65 CIE XYZ に変換したものとする

  2. c2xyzc2絶対D65 CIE XYZ に変換したものとする

  3. w1 = clamp((H - H2) / (H1 - H2), 0, 1)

  4. w2 = clamp((H - H1) / (H2 - H1), 0, 1) (なお、 w2 は 1 - w1 です)

  5. eps = 0.001

  6. cxyz = Array(3)

  7. i が 0 〜 2 の間: cxyz[i] = pow(c1xyz[i] + eps, w1 ) * pow(c2xyz[i] + eps, w2 ) - eps

Note: eps は0除算を防ぐためのものであり、とくにSDR色で黒に近い場合の補間で重要です。

例:c1 = color(rec2100-linear 0.9 1.0 0.8), c2 = color(rec2100-linear 1.8 2.0 1.5), H1 = 0, H2 = 2, H = 1 の場合:
c1xyz = [ 173.156, 195.260, 178.003 ]
c2xyz = [ 342.883, 389.315, 334.467 ]
w1 = 0.5
w2 = 0.5
cxyz = [ 243.664, 275.713, 244.000 ]
例:c1 = color(display-p3 1 1 0.33), c2 = jzczhz(70% 0.14 100), H1 = 0.5, H2 = 4, H = 2 の場合;
c1xyz = [ 156.285, 188.337, 28.015 ]
c2xyz = [ 3776.1434, 4362.407, 1577.913 ]
w1 = 0.571 
w2 = 0.429
cxyz = [ 611.911, 724.180, 157.650 ]

c1はすべてのヘッドルーム値 <= 0.5 でそのまま使われ、c2はヘッドルーム値 >= 4 でそのまま使われることに注意してください。

例えば、c1 = ictcp(50% -0.3 0)、 c2 = ictcp(85% -0.35 0.1)、 H1 = 0、H2 = 4 の場合を考えます。 これは CSS では次のように表現します:
color-hdr(
  var(--c1) 0,
  var(--c2) 4
)

H = 2.3 の場合

c1xyz = [63.6, 96.53, 8.558]
c2xyz = [2521, 2508, 112.2]
w1 = 0.425
w2 = 0.575
cxyz = [527.68, 628.20, 37.59]

6. デバイス非依存HDR色

CSS Color 4 § 9 デバイス非依存色: CIE LabとLCH、OklabおよびOKLChがデバイス非依存SDR色を指定できるようにするのと同様に、 この仕様ではデバイス非依存HDR色を指定できます。

6.1. ICtCp(アイシーティーシーピー)の紹介

このセクションは規範的ではありません。

ICTCP色空間はCIE Labより知覚的な均一性に優れており、 高ダイナミックレンジ(HDR)やワイドカラ―ガマット(WCG)画像向けの 映像・デジタル写真システムのカラーパイプラインの一部として利用されています。

TとPの下付き文字は、 人間の視覚系のトリタノープ(黄-青軸)および プロタノープ(赤-緑軸)の対立色軸を示しています。 下付き文字を省いて ICtCp と表記されることが多いです。

ICTCPは Dolby Laboratories により、EbnerとFairchildのIPT色空間[Development_ITP]をもとに開発され[What_is_ICtCp][Rec_BT.2100]で Constant Intensity ICTCPシグナルフォーマットとして定義されています。 YCbCrの置換を意図しています[Perrin]

ヒトの視覚LMS錐体プライマリがベースであり、 Hunt-Pointer-Estevez(HPE)XYZ→LMS変換が使われ、 D65ホワイトポイントへ正規化されます。 その後、BT.2020 RGBのガマットの凹みを緩和するために 4%クロストーク行列が適用されます[What_is_ICtCp]。 これにより、補間誤差が低減し、一定の色相線やJND(MacAdam楕円)の均一性も向上します。

Labが主に低輝度・反射色で評価されているのに対し、 ICTCPは高彩度(WCG)・自己発光・高輝度(HDR)色で評価されています。

そのため、HDRカラーデルタE測定(deltaE ITP)やSDR/HDR混合時のガマットマッピングにも適しています。

例えば、BT.2020とBT.2100は同じ原色と白色点を採用しています。 BT.2020はSDRで、BT.2100はHDRで HDR基準白が約0.58のコード値になります。

両カラースペースの非常に広い原色赤:

color(rec2100-pq 0.58 0 0) /* ictcp(44.6% -0.129 0.399) */
color(rec2020 1 0 0)       /* ictcp(44.7% -0.130 0.399)  */

ICTCPで2つの色は非常に近く、deltaE ITPは0.487となり、視覚的に差は認められません。

これらの色はsRGB「赤」とは大きく異なります:

color(rec2100-pq 0.58 0 0) /* ictcp(44.6% -0.129 0.399) */
red                        /* ictcp(42.8% -0.116 0.279) */

deltaE ITPは87.7で、見た目でまったく異なる色となります。

6.2. Jzazbz と JzCzhz の紹介

このセクションは規範的ではありません。

Jzazbz色空間[Safdar-PUCS]、 およびその極形式であるJzCzhzは、 BT.2020のような広色域の色に対して より知覚的に均一になるように設計され、 HDR色を含む広範囲の明度を正確に予測し、 知覚属性(明度、彩度、色相)間の相互依存性を 最小限に抑えるように設計されている。 特に、CAM16-UCSと比較して、 優れた色相均一性を持つ[Safdar-PUCS]

CIE Labは、HDR基準白に対する [0%, 100%]範囲の明度スケールを使用する。 同様に、Oklabは[0, 1.0]範囲の明度スケールを使用し、 ここでも1.0はHDR基準白を指す。 これに対し、JzazbzにおけるJz軸は、 [0, 1.0]範囲を持ち、 Perceptual Quantizerに類似した符号化を使用し、 13ストップを超えるダイナミックレンジを表現できる。

6.3. ICtCp

ICtCp色空間は3つの数値パラメータを受け付けます。 Iは強度(LabのLに似るが最大10,000 cd/m2まで)を表し、 CTとCPは 黄青軸(トリタノープ)・赤緑軸(プロタノープ)の反対色軸です(Labのb・aに類似)。

この色空間の特徴:

x y
白色点 D65
トランスファ関数 パーセプチュアルクォンタイザー
白の輝度 203 cd/m²
ピーク白輝度 10,000 cd/m²
黒の輝度 0.001 cd/m²
画像状態 ディスプレイ参照
パーセンテージ I, Ct, Cp で指定可
パーセント基準範囲 I: 0% = 0.0, 100% = 1.0
Ct, Cp: -100% = -0.5, 100% = 0.5

[Rec_BT.2100]は、 線形光BT.2100 RGB [Rec_BT.2100]からの変換によって ICTCPを定義しているが、 この変換はLMSを経由して進むため、 [What_is_ICtCp]に示されているように、 XYZからLMSへの変換を適用することで、 他の任意の色空間も表現できる。 サンプルコードはこの方法を使用している。

この色は ICtCp での sRGB色「lime」を表します
 ictcp(0.5393 -0.2643 -0.0625)
この色は快適な「ディフューズホワイト」を表します。 長時間の表示や字幕用途、どんな面積でも利用できます。 これはsRGBのwhiteと同じ色です。 ディフューズホワイトは203 cd/m²です[Rec_BT.2100]
 ictcp(0.58069 0 0)

relative color 構文内のictcp()関数では、許可される成分キーワードは次のとおりです:

6.4. Jzazbz

Jzazbz色空間は3つの数値パラメータを受け付けます。 Jzは明度(LabのLに類似)、 azおよびbzは赤緑軸および黄青軸 (Labのa, bに類似)を表します。

Jzazbz色空間は次の特徴を持ちます:

x y
白色点 D65
トランスファ関数 パーセプチュアルクォンタイザー
ピーク白輝度 10,000 cd/m²
黒輝度 0.001 cd/m²
画像状態 ディスプレイ参照
パーセンテージ Jz, az, bzで指定可
パーセント基準範囲 Jz: 0% = 0.0, 100% = 1.0
az, bz: -100% = -0.21, 100% = 0.21

Labと異なり、D65白色点が使われることに注意してください。 そのため、ほとんどのRGB空間 (D65白色点を使うもの)では 色順応処理は不要です。

XYZ-D65とJzazbzの変換サンプルコードを提供しています。

この色は快適な「ディフューズホワイト」を表現します。 長時間表示や字幕、画面のどんな面積にも利用できます。 これはsRGBのwhiteと同じ色です。 ディフューズホワイトは203 cd/m²です[Rec_BT.2100]
 jzazbz(0.22207 -0.00016 -0.00012)

relative color構文内のjzazbz()関数で 許可される成分キーワードは次の通りです:

6.5. JzCzhz

LCH(Labの極座標表現)に類似し、JzCzhzJzazbzの極座標形です。

JzJzazbzの値と同じで明度を示し、 Czは彩度(クロマ)を、 hzは色相角を表します。 色相角は正のaz軸から正のbz軸への方向で測定されます。

次の特徴があります:

x y
白色点 D65
トランスファ関数 パーセプチュアルクォンタイザー
ピーク白輝度 10,000 cd/m²
黒輝度 0.001 cd/m²
画像状態 ディスプレイ参照
パーセンテージ Jz, Czで指定可
パーセント基準範囲 Jz: 0% = 0.0, 100% = 1.0
Cz: 0% = 0.0, 100% = 0.26
無効な色相ε Cz <= 0.0000026
この色は、sRGB色「lime」をJzazbzで表したものである
 jzazbz(0.17542 -0.1179 0.1092)
そして、こちらは同じ色を極形式で表したものである
 jzczhz(0.17542 0.1614 132.50)

relative color構文内のjzczhz()関数で 許可される成分キーワードは次の通りです:

6.5.1. Jzazbz色をJzCzhz色へ変換

JzCzhzへの変換は簡単です:

  1. hz = atan2(bz, az) // 度へ変換すること!
  2. Cz = sqrt(az^2 + bz^2)
  3. Jzは同じ

加えて、実用的なコードは Cz がε未満の場合 none 値を返すべきです。

6.5.2. JzCzhz色をJzazbz色へ変換

Jzazbzへの変換は簡単です:

  1. az = Cz cos(H) // まずラジアンに変換すること!
  2. bz = Cz sin(H) // まずラジアンに変換すること!
  3. Jzは同じ

また、実用的なコードは hz がnone の値であるかどうかをチェックしてください。

7. あらかじめ定義されたカラースペースとカスタムカラースペースの指定: color() 関数

color() 関数は 特定のカラースペースで (他のカラ―関数のほとんどが動作する暗黙のsRGBではなく)色を指定できます。

この仕様はcolor()関数を拡張し、 HDR用あらかじめ定義されたカラースペースCSS Color 4 §  10. あらかじめ定義されたカラースペース の規定SDRスペースや CSS Color 5 § 4 相対色の相対カラー構文に加え利用できます。

構文は次の通りです:

<predefined-rgb> = srgb | srgb-linear | display-p3 | display-p3-linear | a98-rgb | prophoto-rgb | rec2020 | 
  rec2100-pq | rec2100-hlg | rec2100-linear

8. HDR用あらかじめ定義されたカラースペース:

CSS Color 4で定義されているSDR カラースペースに加えて、以下のHDRカラースペースが color関数で利用するために定義されています。

これら新しいカラースペースの値のシリアライズは、CSS Color 4 §  16. <color>値のシリアライズ の記述と同一です。

8.1. rec2100-pq

rec2100-pq [Rec_BT.2100] カラースペースは3つの数値パラメータ(赤・緑・青チャンネル)を受け付け、 実際のビット深度(各成分10または12ビット)によらず各値の有効範囲は[0, 1]です。

パーセプチュアルクォンタイザー(PQ)エレクトロオプティカルトランスファ関数が使われます [SMPTE-ST-2084],[Rec_BT.2100]。 PQは基準視聴条件として、 画面の周囲が5 cd/m²であることを前提とします。

ITU-R 2100は4Kおよび8K HDRテレビで利用されます。

主な特徴は以下のとおりです(ディスプレイの原色は[Rec.2020]と同じ):

x y
赤の色度 0.708 0.292
緑の色度 0.170 0.797
青の色度 0.131 0.046
白の色度 D65
トランスファ関数 パーセプチュアルクォンタイザー
白の輝度 203 cd/m²
ピーク白輝度 10,000 cd/m²
黒の輝度 ≤ 0.005 cd/m²
画像状態 ディスプレイ参照
パーセンテージ R, G, Bで指定可
パーセント基準範囲 R, G, B: 0% = 0.0, 100% = 1.0

非基準視聴環境下のナローPQビデオ、 または任意の環境下でのHLGの場合は、 黒レベルを [Rec_BT.814] 付属書のPLUGEテスト信号と手順で調整する必要があります。 CSSでのPQ値(ワイドレンジ)は、黒がコードポイント0に対応します。

この色は輝度10,000 cd/m²の眩しい白を表します。 このような明るい色はごく短時間、画面のごく一部でしか表示できません。 通常、コンテンツはより低いピークホワイト(例:4,000cd/m²)でマスタリングされます。
 color(rec2100-pq 1.0 1.0 1.0);
この色は、快適な「拡散白」を表す。 この色は長時間表示でき、 または字幕に使用でき、 画面上の任意の大きさの領域で用いることができる。 これはsRGBのwhiteと同じ色である。 拡散白は203 cd/m²である[Rec_BT.2100]
 color(rec2100-pq 0.58 0.58 0.58);
この色は中間グレーを表す。 写真家の「18%反射率グレー」カードのようなもので、 17 cd/m²である。
 color(rec2100-pq 0.34 0.34 0.34)

sRGBの赤、緑、青およびP3の赤、緑、青の符号化を含む、 他の例を追加する。

線形光RGB信号は、次のようにPQ符号化へ変換される。 PQにおける符号化可能な最大値(ピーク、小面積白)は10,000 cd/m²である。 HDR基準白は203 cd/m²である[Rpt_BT.2408-9]

var Er;			// 赤、緑、または青の成分。SDRでは[0, 1]、HDRでは[0, およそ70]
var Yw = 203;	// 拡散白の輝度、cd/m²
var x = Er * Yw / 10000; 	// ピーク白の輝度は10,000 cd/m²である。
const n = 2610 / (2 ** 14);
const m = 2523 / (2 ** 5);
const c1 = 3424 / (2 ** 12);
const c2 = 2413 / (2 ** 7);
const c3 = 2392 / (2 ** 7);
xPQ = (((c1 + (c2 * (x ** n))) / (1 + (c3 * (x ** n)))) ** m);

xPQは「ガンマ補正済み」(OETF調整済み)の信号[0, 1]である。

PQ符号化値は、次のように線形光へ変換される:

var xPQ;			// 赤、緑、または青のPQ符号化成分、[0, 1]
const ninv = (2 ** 14) / 2610;
const minv = (2 ** 5) / 2523;
const c1 = 3424 / (2 ** 12);
const c2 = 2413 / (2 ** 7);
const c3 = 2392 / (2 ** 7);
var x = (((Math.max(((xPQ ** minv) - c1), 0) / (c2 - (c3 * (xPQ ** minv)))) ** ninv);
var Yw = 203;			// 拡散白の輝度、cd/m²
var Ea = x * 10000; 	// 輝度、[0, 10,000]。
var Er = x * 10000 / Yw; 	// 拡散白に対する相対輝度、[0, およそ70]。

8.2. rec2100-hlg

rec2100-hlg [Rec_BT.2100] カラースペースは3つの数値パラメータ(赤・緑・青チャンネル)を受け付け、 実際のビット深度(各成分10または12ビット)によらず各値の有効範囲は[0, 1]です。

ハイブリッドログガンマ(HLG)エレクトロオプティカルトランスファ関数が使われます [ARIB_STD-B67],[Rec_BT.2100]。 HLGはさまざまな明るさや視聴環境で使用でき、 全体的な明るさはユーザーが調整可能です。 0.75は「ディフューズ」または「メディアホワイト」を表し、 「18%反射率グレー」カードは0.38です[Rec_BT.2390]

主な特徴は以下のとおりです(ディスプレイの原色は[Rec.2020]と同じ):

x y
赤の色度 0.708 0.292
緑の色度 0.170 0.797
青の色度 0.131 0.046
白の色度 D65
トランスファ関数 ハイブリッドログガンマ
白の輝度 視聴条件に依存
ピーク白輝度 基準白の12倍
黒の輝度 基準白による、本文参照
画像状態 シーン参照
パーセンテージ R, G, Bで指定可
パーセント基準範囲 R, G, B: 0% = 0.0, 100% = 1.0

ナローHLGビデオ(任意環境)では、 黒レベルは [Rec_BT.814] 付録4のPLUGEテスト信号と手法で調整する必要があります。

CSSでのHLG値(ワイドレンジ)では黒がコードポイント0に対応します。

他の例を追加すること

この色は、快適な「拡散白」を表す。 この色は長時間表示でき、 または字幕に使用でき、 画面上の任意の大きさの領域で用いることができる。 コンテンツは通常、ピーク白が 1,000から4,000 cd/m²になるようにマスタリングされるため、 拡散白は203から581 cd/m²になる。
 color(rec2100-hlg 0.75 0.75 0.75);
この色は中間グレーを表し、 26から104 cd/m²である。
 color(rec2100-hlg 0.38 0.38 0.38)

線形光RGB信号は、次のようにHLG符号化へ変換される[Rec_BT.2390]

var E;			// 赤、緑、または青の成分、[0, 1]
const a = 0.17883277;
const b = 0.28466892;   // 1 - (4 * a)
const c = 0.55991073;   // 0.5 - a * Math.log(4 *a)
// 負の値を処理する
var sign = E < 0? -1 : 1;
var abs = Math.abs(E);
if (abs <= 1/12) {
  Edash = sign * Math.sqrt( 3 * abs);
}
else {
  Edash = a * Math.log(12 * E - b) + c;
}
Edashは「ガンマ補正済み」(OETF調整済み)の信号である。

逆変換(HLG符号化から線形光へ)は次のとおりである[Rec_BT.2390]::

var Edash;			// 赤、緑、または青の符号化成分、[0, 1]
const a = 0.17883277;
const b = 0.28466892;   // 1 - (4 * a)
const c = 0.55991073;   // 0.5 - a * Math.log(4 *a)
if (Edash <= 0.5) {
  E = (Edash ** 2) / 3;
}
else {
  E = (Math.exp((Edash - c) / a) + b) / 12;
}

同じページで定義されている黒レベルリフトΒを 追加するか?

8.3. rec2100-linear

rec2100-linear [Rec_BT.2100] カラースペースは3つの数値パラメータ(赤・緑・青チャンネル)を受け付け、 実際のビット深度(各成分10または12ビット)によらず、名目上の範囲は[0, 1]です。

赤、緑、青がすべて1.0である色は、 輝度203 cd/m²のHDR 基準白を表す。

color(rec2100-linear 1 1 1)
例えば、次の色
color(rec2100-linear 9.852 9.852 9.852)

は、輝度9.852 × 203 = 1,999cd/m²の白いハイライトを表します。

この色は快適な「ディフューズホワイト」を表します。 長時間表示や字幕用途、どんな面積でも利用できます。 これはsRGBのwhiteと同じ色です。 ディフューズホワイトは203 cd/m²です[Rec_BT.2100]
 color(rec2100-linear 1 1 1)

リニアライトのエレクトロオプティカルトランスファ関数が使われます。

主な特徴は以下のとおりです(ディスプレイの原色は[Rec.2020]と同じ):

x y
赤の色度 0.708 0.292
緑の色度 0.170 0.797
青の色度 0.131 0.046
白の色度 D65
トランスファ関数 リニア
白の輝度 203 cd/m²
ピーク白輝度 10,000 cd/m²
黒の輝度 0.001 cd/m²
画像状態 ディスプレイ参照
パーセンテージ R, G, Bで指定可
パーセント基準範囲 R, G, B: 0% = 0.0, 100% = 1.0

9. SDRとHDRコンテンツの合成

合成はCIE XYZで行うべきである。 これは、色域の制限を持たない線形光空間であるためである。 実装は、代わりに線形光RGB空間で合成することを選択してもよい。 その場合でも、色域外の値(負の値、または100%を超える値)が 正しく処理され、 デバイス色空間への最終的な転送まで クリップまたは色域マッピングされないなら、 同じ結果が得られる。

HLG伝達関数を使用するHDRは、 SDRのHDR基準白を、 75% HLG値を表示するために使用される輝度と同じ輝度に マッピングしなければならない。[SMPTE-ST-2084]

詳細については、ITU Rpt_BT.2408-0の表3および表4も参照されたい[Rpt_BT.2408-9]

PQ伝達関数を使用するHDRは、 SDRのHDR基準白を、 58% PQ値を表示するために使用される輝度と同じである203 cd/m²に マッピングするべきである。[SMPTE-ST-2084]

ただし、実装は、非基準の視聴条件を考慮するために、 色の再レンダリング手順を組み込むことを選択してもよい。

10. <color> 値のシリアライズ

10.1. color() 関数の値のシリアライズ

このセクションは CSS Color 4 § 16.5 color()関数値のシリアライズを拡張します。

color()値のシリアライズ形式は、 算出値に基づき、 color()形式を使います。 関数名およびカラースペース名はASCII小文字

成分値は10進数で、 <number>としてシリアライズされます。 各成分、およびカラースペース名と先頭成分の間は ASCIIスペース" "で区切ります。

あらかじめ定義されたHDRカラースペースの 最低往復精度は下表の通りです:

HDRカラースペース 最低ビット数
rec2100-pq, rec2100-hlg 10
rec2100-linear, jzazbz, jzczhz, ictcp 16

(内部保存にはコンポーネントごと16bit, half-float, float推奨)、 値は+∞方向丸め、 切り捨て不可です。

11. 色変換のサンプルコード

このセクションは規範的ではありません。

テスト

このセクションは規範的ではないため、テストは必要ありません。


明確さのため、行列の乗算にはライブラリを使用します。 (すべての乗算と加算をインラインで書くより可読性が高くなります)。 行列は列優先 順序(column-major order)です。

このコードはまた、CSS Color 4 § 19 色変換のサンプルコードの すべての変換コードが利用可能であることを前提とします。

Jzazbzで使用されるLMSは ICtCpで使用されるものとは異なるため、 正しい方を使用するよう注意してください!

11.1. rec2100-linear のサンプルコード

BT.2020 と BT.2100 のカラースペースは 同じRGB原色と白色点を使用し、 どちらもHDR基準白をコンポーネント値 1.0 に配置します。

// これらの関数は CSS Color 4 の色変換関数を使用します

function XYZ_to_lin_2100(XYZ) {
    // D65 の XYZ 配列をリニアライト BT.2100 RGB に変換
    // [0,0,0] が黒、[1,1,1] がメディアホワイト
    // 1 を超えるコンポーネント値は HDR 色を示す

    return  XYZ_to_lin_2020(XYZ);
}

function lin_2100_to_XYZ(RGB) {
    // リニアライト BT.2100 RGB の配列を
    // D65 XYZ に変換

    return lin_2020_to_XYZ(RGB);
}

11.2. rec2100-pq のサンプルコード

function XYZ_to_pq_2100(XYZ) {
    // D65 の XYZ 配列を PQ エンコード BT.2100 RGB に変換
    // [0,0,0] が黒、[1,1,1] が 10,000 cd/m^2 の白
    // メディアホワイトは [0.5807,0.5807,0.5807](有効数字4桁)

    let linRGB = XYZ_to_lin_2100(XYZ);
    return pq_encode(linRGB);
}

function pq_2100_to_XYZ(RGB) {
    // PQ エンコード BT.2100 RGB の配列を
    // D65 XYZ に変換

    let linRGB = pq_decode(RGB);
    return lin_2100_to_XYZ(linRGB);
}

function pq_encode(RGB) {

    const Yw = 203;    // メディアホワイトの絶対輝度(cd/m²)
    const n = 2610 / (2 ** 14);
    const m = 2523 / (2 ** 5);
    const c1 = 3424 / (2 ** 12);
    const c2 = 2413 / (2 ** 7);
    const c3 = 2392 / (2 ** 7);

    // 入力:範囲 [0,1] の PQ エンコード成分
    // 出力:メディアホワイト相対のリニアライト
    return RGB.map(function (val) {
        let x = Math.max(val * Yw / 10000, 0);     // ピーク白の絶対輝度は 10,000 cd/m²
        let num = (c1 + (c2 * (x ** n)));
        let denom = (1 + (c3 * (x ** n)));

        return ((num / denom)  ** m);
    });
}

function pq_decode(RGB) {

    const Yw = 203;    // メディアホワイトの絶対輝度(cd/m²)
    const ninv = (2 ** 14) / 2610;
    const minv = (2 ** 5) / 2523;
    const c1 = 3424 / (2 ** 12);
    const c2 = 2413 / (2 ** 7);
    const c3 = 2392 / (2 ** 7);

    // 入力:範囲 [0,1] の PQ エンコード成分
    // 出力:メディアホワイト相対のリニアライト
    return RGB.map(function (val) {
        let x = ((Math.max(((val ** minv) - c1), 0) / (c2 - (c3 * (val ** minv)))) ** ninv);
        return (x * 10000 / Yw);     // メディアホワイト相対輝度 [0, 約70]
    });
}

11.3. rec2100-hlg のサンプルコード

function XYZ_to_hlg_2100(XYZ) {
    // D65 の XYZ 配列を HLG エンコード BT.2100 RGB に変換
    // [0,0,0] が黒、[0.75,0.75,0.75] がメディアホワイト

    let linRGB = XYZ_to_lin_2100(XYZ);
    return hlg_encode(linRGB);
}

function hlg_2100_to_XYZ(RGB) {
    // PQ エンコード BT.2100 RGB の配列を
    // D65 XYZ に変換

    let linRGB = hlg_decode(RGB);
    return lin_2100_to_XYZ(linRGB);
}

function hlg_encode(RGB) {

    const a = 0.17883277;
    const b = 0.28466892; // 1 - (4 * a)
    const c = 0.55991073; // 0.5 - a * Math.log(4 *a)
    const scale = 3.7743;    // 18% グレーを HLG 0.38 に、メディアホワイトを 0.75 に

    return RGB.map(function (val) {
        // まずスケールして、リニアライトのメディアホワイトを 1/3 に置く
        val /= scale;
        // HLG の OETF
        // ITU-R BT.2390-10 p.23
        // 6.1 The hybrid log-gamma opto-electronic transfer function (OETF)
        if (val <= 1 / 12) {
            return spow(3 * val, 0.5);
        }
        return a * Math.log(12 * val - b) + c;
    });
}

function hlg_decode(RGB) {

    const a = 0.17883277;
    const b = 0.28466892; // 1 - (4 * a)
    const c = 0.55991073; // 0.5 - a * Math.log(4 *a)
    const scale = 3.7743;    // 18% グレーを HLG 0.38 に、メディアホワイトを 0.75 に

    return RGB.map(function (val) {
        // まず HLG の EOTF
        // ITU-R BT.2390-10 p.30
        // 6.3 The hybrid log-gamma electro-optical transfer function (EOTF)
        // その後 3 倍してメディアホワイトを 1.0 に
        if (val <= 0.5) {
            return (val ** 2) / 3 * scale;
        }
        return ((Math.exp((val - c) / a) + b) / 12) * scale;
    });
}

function spow (base, exp) {
    let sign = base < 0? -1 : 1;
    return sign * (Math.abs(base) ** exp);
}

11.4. jzazbz のサンプルコード

上で定義した符号付きべき(spow)関数を使用します。

function XYZ_to_Jzazbz (XYZ) {
    // D65 の XYZ 配列を JzAzBz に変換
    // [0,0,0] が黒で、
    // メディアホワイトは [0.2220, -0.00016, -0.0001]

    const Yw = 203; // メディアホワイトの絶対輝度
    const M = [
        [  0.41478972, 0.579999,  0.0146480 ],
        [ -0.2015100,  1.120649,  0.0531008 ],
        [ -0.0166008,  0.264800,  0.6684799 ],
    ];
    const b = 1.15;
    const g = 0.66;

    // まず XYZ をメディアホワイト相対ではなく絶対値に
    // PQ の最大輝度は 10,000 cd/m²
    // BT.2048 によればメディアホワイトは Y=203 cd/m²
    let [Xa, Ya, Za] = XYZ.map(v => v * Yw);

    // つぎに X と Y を調整して、青の曲率を最小化
    let Xm = b * Xa - (b - 1) * Za;
    let Ym = g * Ya - (g - 1) * Xa;

    // LMS 錐体領域へ
    let LMS = multiplyMatrices(M, [Xm, Ym, Za]);
    return LMStoJzazbz(LMS);
}

function LMStoJzazbz(LMS) {

    const M = [
        [  0.5,       0.5,       0        ],
        [  3.524000, -4.066708,  0.542708 ],
        [  0.199076,  1.096799, -1.295875 ],
    ];
    const c1 = 3424 / 2 ** 12;
    const c2 = 2413 / 2 ** 7);
    const c3 = 2392 / 2 ** 7;
    const n = 2610 / 2 ** 14;
    const p = (1.7 * 2523) / 2 ** 5;    // 通常の PQ に対して 1.7 倍のスケール
    const d = -0.56;
    const d0 = 1.6295499532821566e-11;  // 黒を 0 に戻すための微小シフト


    // LMS を PQ 符号化
    let PQLMS = (
        LMS.map(function (val) {
            let num = c1 + c2 * spow((val / 10000), n);
            let denom = 1 + c3 * spow((val / 10000), n);

            return spow((num / denom), p);
        })
    );

    // Iz, az, bz を計算
    let [Iz, az, bz] = multiplyMatrices(M, PQLMS);
    // Iz から Jz を導出
    let Jz = ((1 + d) * Iz) / (1 + d * Iz) - d0;
    return [Jz, az, bz];
}

function Jzazbz_to_XYZ (Jzazbz) {
    // JzAzBz の配列を D65 XYZ に変換
    // [0,0,0] が黒で、
    // メディアホワイトは [0.2220, -0.00016, -0.0001]

    const b = 1.15;
    const g = 0.66;
    const M = [
        [  1.9242264357876067,  -1.0047923125953657,  0.037651404030618   ],
        [  0.35031676209499907,  0.7264811939316552, -0.06538442294808501 ],
        [ -0.09098281098284752, -0.3127282905230739,  1.5227665613052603  ],
    ];

    let LMS = Jzazbz_to_LMS (Jzazbz);
    // 調整済みの絶対 XYZ
	let [Xm, Ym, Za] = multiplyMatrices(LMS, M);

    // X と Y の調整を戻し、メディアホワイト相対の D65 XYZ を得る
    let Xa = (Xm + (b - 1) * Za) / b;
    let Ya = (Ym + (g - 1) * Xa) / g;
    return [Xa, Ya, Za];
}

function Jzazbz_to_LMS (Jzazbz) {

    const d = -0.56;
    const d0 = 1.6295499532821566e-11;
    const c1 = 3424 / 2 ** 12;
    const c2 = 2413 / 2 ** 7;
    const c3 = 2392 / 2 ** 7;
    const pinv = 2 ** 5 / (1.7 * 2523);
    const M = [
        [ 1,  0.13860504327153927,   0.05804731615611883  ],
        [ 1, -0.1386050432715393,   -0.058047316156118904 ],
        [ 1, -0.09601924202631895,  -0.81189189605603900  ],
    ];

    let [Jz, az, bz] = Jzazbz;
	let Iz = (Jz + d0) / (1 + d - d * (Jz + d0));

    // LMS 錐体領域へ
	let PQLMS = multiplyMatrices([Iz, az, bz], M);

    // PQ 符号化からリニアライト LMS に変換
    let LMS = (
        PQLMS.map(function (val) {
            let num = c1 - spow(val, pinv);
            let denom = c3 * spow(val, pinv) - c2;
            let x = 10000 * spow(num / denom, ninv);

            return x; // メディアホワイト相対輝度 [0, 約70]
        })
    );
    return LMS;
}

11.5. ICtCp のサンプルコード

まず rec2100-linear に変換することを要求せず、 (これは[Rec_BT.2100]で定義されている手順) ほかの色変換コードとの互換性のため、 このサンプルコードでは絶対 CIE XYZ から直接進めます。

4% のクロストーク行列と色相回転も XYZ から LMS へのステップに組み込み、 3つの別ステップとして適用しません。

最終結果は同一で、単に手順が少ないだけです。

function XYZ_to_ICtCp (XYZ) {
    // D65 XYZ の配列を ICtCp に変換

    // 以下の行列には 4% のクロストーク成分が含まれ、
    // Dolby の "What is ICtCp" 論文の手順に基づく
    const M = [
        [  0.3592832590121217,  0.6976051147779502, -0.0358915932320290 ],
        [ -0.1920808463704993,  1.1004767970374321,  0.0753748658519118 ],
        [  0.0070797844607479,  0.0748396662186362,  0.8433265453898765 ],
    ];

    let LMS = multiplyMatrices(M, XYZ.map(v => v * Yw));
    return LMStoICtCp(LMS);
}

function LMStoICtCp (LMS) {

    const c1 = 3424 / 4096;
    const c2 = 2413 / 128;
    const c3 = 2392 / 128;
    const m1 = 2610 / 16384;
    const m2 = 2523 / 32;

    // この行列には Ebner の LMS 係数、回転、
    // および [-0.5, 0.5] 範囲へのスケーリングが含まれる
    // 有理係数は Fröhlich p.97 と ITU-R BT.2124-0 pp.2-3 に基づく
    const M = [
        [  2048 / 4096,   2048 / 4096,       0      ],
        [  6610 / 4096, -13613 / 4096,  7003 / 4096 ],
        [ 17933 / 4096, -17390 / 4096,  -543 / 4096 ],
    ];

    // PQ の EOTF を適用
    // [0, 10,000] が [0, 1] にマップされるようスケーリング
    // 分母に「1 +」があるため 0 除算は起こらない
    let PQLMS = LMS.map (function (val) {
        let num = c1 + (c2 * ((val / 10000) ** m1));
        let denom = 1 + (c3 * ((val / 10000) ** m1));

        return (num / denom)  ** m2;
    });

    // Y'C'bC'r 互換のための回転を含む LMS→IPT 変換
    return multiplyMatrices(M, PQLMS);
}

function ICtCp_to_XYZ (ICtCp) {
    // ICtCp を絶対 D65 XYZ 配列に変換

    const M = [
        [  2.0701522183894223, -1.3263473389671563,  0.2066510476294053 ],
        [  0.3647385209748072,  0.6805660249472273, -0.0453045459220347 ],
        [ -0.0497472075358123, -0.0492609666966131,  1.1880659249923042 ],
    ];

    let LMS = ICtCptoLMS(ICtCp);
    return multiplyMatrices(M, LMS);
}

function ICtCptoLMS (ICtCp) {

    const c1 = 3424 / 4096;
    const c2 = 2413 / 128;
    const c3 = 2392 / 128;
    const im1 = 16384 / 2610;
    const im2 = 32 / 2523;

    const M = [
        [ 0.9999999999999998,  0.0086090370379328,  0.1110296250030260 ],
        [ 0.9999999999999998, -0.0086090370379328, -0.1110296250030259 ],
        [ 0.9999999999999998,  0.5600313357106791, -0.3206271749873188 ],
    ];

    let PQLMS = multiplyMatrices(M, ICtCp);

    // PQ 符号化を元に戻す(BT.2124-0 付録2 Conversion 3)
    let LMS = PQLMS.map (function (val) {
        let num  = Math.max((val ** im2) - c1, 0);
        let denom = (c2 - (c3 * (val ** im2)));
        return 10000 * ((num / denom) ** im1);
    });

    return LMS;
}

11.6. hdr-color() のサンプルコード

function hdrColor(col1, H1, col2, H2, H) {

    // col1, col2 は絶対 XYZ の 2 色を表す配列
    // H1, H2 は各色のヘッドルーム(ストップ単位、すなわち対数スケール、0 = SDR)
    // H は利用可能なヘッドルーム

    // まずヘッドルームが異なることを確認
    if (H1 == H2) return 0;

    let w1 = clamp((H - H2) / (H1 - H2), 0, 1);
    let w2 = clamp((H - H1) / (H2 - H1), 0, 1);
    let eps = 0.001;
    let cxyz = Array(3);
    for (let i=0; i<3; i++) {
        cxyz[i] = Math.pow(c1xyz[i] + eps, w1) * Math.pow(c2xyz[i] + eps, w2) - eps;
    }
    return cxyz;
}

const clamp = (n, min, max) =>
  Math.min(Math.max(n, min), max)

12. ΔEITP 色差のサンプルコード

このセクションは規範的ではありません。

テスト

このセクションは規範的ではないため、テストは必要ありません。


ΔEITP [Rec_BT.2124] 色差指標は、 HDR または SDR/HDR 混在の文脈において、 2 つのディスプレイ参照色の 知覚的な色差を測るために使用できます。 たとえばディスプレイのキャリブレーションや ガマット/トーンマッピングなどです。

これは ICtCp 色空間におけるユークリッド距離で、 ΔEITP が 1.0 のとき ちょうど知覚可能な差を 1 とするようスケーリングされています。

// deltaE ITP を計算
// スケーリングされた二乗和平方根
// ITU-R BT.2124-0 付録 1
/**
 * @param {number[]} reference - ICtCp の配列: I は 0..1、Ct/Cp は -1..1
 * @param {number[]} sample -    ICtCp の配列: I は 0..1、Ct/Cp は -1..1
 * @return {number} 参照色からサンプル色がどれだけ異なるか
 */
function deltaEITP (reference, sample) {
    let [I1, Ct1, Cp1] = reference;
	let [I2, Ct2, Cp2] = sample;
	let ΔI = I1 - I2;
	let ΔT = 0.5 * (Ct1 - Ct2);
	let ΔP = Cp1 - Cp2;
	return 720 * Math.sqrt(ΔI ** 2 + ΔT ** 2 + ΔP ** 2);
}

プライバシーに関する考慮事項

Web プラットフォームが HDR ヘッドルーム の数値を直接公開しない理由は、 それによって現在の視聴環境が露出し、 プライバシー侵害となるためです。

セキュリティに関する考慮事項

本ドキュメントに関してセキュリティ上の懸念は提起されていません

アクセシビリティに関する考慮事項

非常に明るい色に敏感な人がいるため、 ユーザーエージェントはユーザーの選択で最大輝度を制限できる仕組みを提供すべきです。適切な手法として、 [Rec_BT.2390] のセクション 5.4.1 制限された輝度範囲のディスプレイへのマッピング にあるトー/ニー手順が推奨されます。

dynamic-range-limit プロパティは、ユーザースタイルシートで standard または constrained に設定することもできます。

変更点

2026年3月3日付作業草案 以降の変更点

2024年12月17日付 初公開作業草案 以降の変更点

適合性

文書上の規約

適合性要件は記述的主張と RFC 2119 用語の組み合わせで表現されます。強調語句 “MUST”、 “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, および “OPTIONAL” は、規範的部分では RFC 2119 に記載された通りに解釈されます。 可読性のため、これらの語句は本仕様では全て大文字で表記されていない場合があります。

本仕様のテキストは、明示的に非規範とされているセクション、例、注を除いてすべて規範的です。 [RFC2119]

本仕様の例は "for example" という語で導入されるか、class="example" で規範的テキストから区別されます。

これは情報的な例の例です。

情報的注記は "Note" という語で始まり、class="note" によって規範的テキストから区別されます。

注: これは情報的な注記です。

勧告は注意を促すための規範セクションであり、<strong class="advisement"> によって区別されます。例: UAs MUST provide an accessible alternative.

Tests

この仕様の内容に関するテストは、このような "Tests" ブロックに記述されることがあります。 そのようなブロックはすべて非規範的です。


適合クラス

本仕様への適合は 3 つの適合クラスで定義されています:

style sheet
CSS スタイルシート
renderer
スタイルシートの意味を解釈し、それを用いて文書をレンダリングする UA
authoring tool
スタイルシートを書く UA

スタイルシートが本仕様に適合するのは、本モジュールで定義された文法を用いる宣言がすべてジェネリックな CSS 文法および各機能の文法に従って有効である場合です。

レンダラーが本仕様に適合するのは、適切な仕様群に従ってスタイルシートを解釈することに加え、本仕様で定義されたすべての機能を正しく解析して文書をレンダリングできることが条件です。ただし、デバイスの制約により正しくレンダリングできない場合があっても、UA が非適合と見なされるわけではありません(例: モノクロモニターでの色表示が不要であること)。

オーサリングツールが本仕様に適合するのは、ジェネリックな CSS 文法および本モジュールの各機能の文法に従って文法的に正しいスタイルシートを書き、スタイルシートに関するすべての適合要件を満たす場合です。

部分実装

フォワード互換性のある解析規則を利用してフォールバック値を割り当てられるように、CSS レンダラーはサポートレベルが利用できない at-rule、プロパティ、プロパティ値、キーワード、およびその他の構文構成要素を無効(適切に 無視)として扱う必要があります。特に、サポートされないコンポーネント値がある場合、単一の複数値プロパティ宣言内でサポートされる値だけを選択的に無視せずに残すことはできません: いずれかの値が無効(サポートされない値は無効とされる)であれば、CSS は宣言全体を無視することを要求します。

不安定および独自機能の実装

将来の安定した CSS 機能との衝突を避けるため、CSSWG は ベストプラクティス に従うことを推奨します。

非実験的実装

仕様が Candidate Recommendation ステージに達すると、非実験的な実装が可能になり、実装者は CR レベルの機能を正しく実装したことを示せる場合、接頭辞なしの実装をリリースするべきです。

CSS の相互運用性を確立・維持するために、CSSWG は非実験的な CSS レンダラーに対して、接頭辞なし実装をリリースする前に実装報告(および必要ならその実装報告に使用したテストケース)を W3C に提出するよう要請しています。W3C に提出されたテストケースは CSS Working Group によるレビューと修正の対象になります。

テストケースおよび実装報告の提出方法については、CSS Working Group のウェブサイト https://www.w3.org/Style/CSS/Test/ を参照してください。質問は public-css-testsuite@w3.org メーリングリストへどうぞ。

索引

本仕様で定義されている用語

参照によって定義された用語

参考文献

規範的参考文献

[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS カスケーディングと継承レベル5. 2022年1月13日. CR. URL: https://www.w3.org/TR/css-cascade-5/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS色モジュール レベル4. 2026年6月18日. CRD. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; Una Kravets; Lea Verou. CSS色モジュール レベル5. 2026年6月18日. WD. URL: https://www.w3.org/TR/css-color-5/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS値と単位 モジュールレベル3. 2024年3月22日. CRD. URL: https://www.w3.org/TR/css-values-3/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS値と単位 モジュールレベル4. 2024年3月12日. WD. URL: https://www.w3.org/TR/css-values-4/
[CSS2]
Bert Bos; et al. カスケーディングスタイルシート レベル2 改訂1(CSS 2.1)仕様. 2011年6月7日. REC. URL: https://www.w3.org/TR/CSS2/
[Rec.2020]
勧告 ITU-R BT.2020-2:制作および国際番組交換用の 超高精細テレビジョンシステムのパラメーター値. 2015年10月. URL: http://www.itu.int/rec/R-REC-BT.2020/en
[Rec_BT.2100]
ITU-R BT.2100-3 制作および国際番組交換で使用する高ダイナミックレンジテレビジョンの画像パラメーター値. 2025年2月. URL: https://www.itu.int/rec/recommendation.asp?lang=en&parent=R-REC-BT.2100-3-202502-I
[Rec_BT.2390]
制作および国際番組交換用の 高ダイナミックレンジテレビジョン. 2025年3月. URL: https://www.itu.int/pub/R-REP-BT.2390-12-2025
[RFC2119]
S. Bradner. RFCにおいて 要求レベルを示すために用いられるキーワード. 1997年3月. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[Rpt_BT.2408-9]
高ダイナミックレンジテレビジョン制作における 運用実務のための指針. 2026年3月. URL: https://www.itu.int/pub/R-REP-BT.2408-9-2026
[Safdar-PUCS]
Safdar, Muhammad; et al. 高ダイナミックレンジおよび広色域を含む画像信号のための 知覚的に均一な色空間. 2017年 6月26日. URL: https://opg.optica.org/oe/fulltext.cfm?uri=oe-25-13-15131&id=368272
[SMPTE-ST-2084]
ST 2084:2014 - SMPTE標準 - マスタリング基準ディスプレイの高ダイナミックレンジ電気光学伝達関数. 2014年 8月29日. URL: https://pub.smpte.org/latest/st2084/st2084-2014.pdf

参考情報

[ARIB_STD-B67]
番組制作のための拡張画像ダイナミックレンジテレビジョン(EIDRTV)システムの 基本パラメーター値. 2015年7月3日. URL: https://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf
[Development_ITP]
F.Ebner; M.D.Fairchild. 色相均一性を改善した色空間(IPT)の開発 および試験。第6回カラー イメージング会議予稿集、8-13、1998. 1998年1月. URL: https://www.researchgate.net/publication/221677980_Development_and_Testing_of_a_Color_Space_IPT_with_Improved_Hue_Uniformity
[DisplayHDR]
CTS 1.2におけるDisplayHDR仕様の概要. 2024年5月17日. URL: https://displayhdr.org/performance-criteria/
[ISO_21496-1]
画像変換のためのゲインマップメタデータ:第1部: ダイナミックレンジ変換. URL: https://www.iso.org/standard/86775.html
[Perrin]
Perrin, A-F.; et al. ICtCp対Y'CbCr: HDRおよびWCGのためのICtCp色空間と適応リシェイパーの評価. 2018年5月. URL: https://ieeexplore.ieee.org/document/8333011
[Rec_BT.2124]
ITU-R BT.2124-0 テレビジョンにおける色差の潜在的な可視性を評価するための客観指標. 2019年1月. URL: https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2124-0-201901-I!!PDF-E.pdf
[Rec_BT.814]
ディスプレイの 明るさおよびコントラスト設定のためのPLUGE試験信号と調整手順の仕様. 2018年7月. URL: https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.814-4-201807-I!!PDF-E.pdf
[SMPTE-ST-2094-50]
色ボリューム変換のための動的メタデータ - アプリケーション#5(放送). 2025年. URL: https://github.com/SMPTE/st2094-50
[What_is_ICtCp]
ICtCpとは何か、 v7.1. URL: https://professional.dolby.com/siteassets/pdfs/ictcp_dolbywhitepaper_v071.pdf

プロパティ索引

名前 初期値 適用対象 継承 パーセンテージ アニメーション型 正規順序 算出値
dynamic-range-limit standard | no-limit | constrained | <dynamic-range-limit-mix()> no-limit すべての要素 はい 該当なし dynamic-range-limit-mix() による 文法通り dynamic-range-limit の算出値を参照

課題索引

対数スケールでSDRとHDRのダイナミックレンジを示す図を追加する
sRGBの赤・緑・青およびP3の赤・緑・青のエンコードを含む、他の例を追加する
他の例を追加する
同ページで定義されている黒レベルリフトΒを追加する?