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

W3C 最初の公開作業草案

この文書の詳細
このバージョン:
https://www.w3.org/TR/2025/WD-css-color-hdr-1-20251202/
最新公開バージョン:
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. ダイナミックレンジの定義

ダイナミックレンジとは、 輝度のうち、最も明るい色と最も暗い色の差です。 ダイナミックレンジは写真用語のストップで測定されます。 1ストップは輝度が2倍になることを意味します。

function DynamicRange (high, low) {
  return Math.log2(high) - Math.log2(low);
  } 

HDR基準白 (メディアホワイトとも呼ばれる)は、通常の白い背景や 暗い背景上の白いテキストの色です。 画面全体で快適に見られる色です。

標準ダイナミックレンジ(SDR)では、 HDR基準白も 最も明るい色であり、 赤・緑・青全てが最大強度で発色したときの色です。

例えば、 sRGBでは、 標準視聴環境下で 白の輝度は80cd/m²、 黒の輝度は0.2cd/m²に定義されています。 この場合、ダイナミックレンジは8.6ストップです。

画面の全体的な輝度はユーザーの好みや標準とは異なる視聴条件に合わせて 調整されることが一般的です。

SDRの場合、画面を明るくしてもダイナミックレンジは変化しません。 なぜなら最も暗い色も同様に明るくなるからです。

例えば、sRGBの画面で 白の輝度を160cd/m²、 最も暗い黒の輝度を0.4cd/m²に設定したとします。 ダイナミックレンジは依然として8.6ストップです。

ハイダイナミックレンジ (HDR)では、 HDR基準白よりも明るい色を表示できます。 たとえば、HDRディスプレイでHDR基準白が203cd/m²に設定されていても、 小さなハイライトで1000cd/m²を表示できる場合があります。 通常、最も明るい色は 画面のごく一部、かつ限られた時間のみ表示されます。 これは消費電力や発熱による制約のためです。

たとえば、HDR基準マスタリングディスプレイでは、 小面積ピークホワイトの輝度が1000cd/m²、 最も暗い黒の輝度が0.05cd/m²の場合、 ダイナミックレンジは14.3ストップです。

HDRでは、画面を明るくするとダイナミックレンジが広がりますが、 HDR基準白の輝度は一定です。

たとえば、rec2100-pqカラースペース([Rec_BT.2100]で定義)の場合、 最も明るいピークホワイトは10,000cd/m²、 最も暗い黒は0.001cd/m²と定義されており、 エンコードされたダイナミックレンジは23.3ストップです。

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

§ 9 SDRとHDRコンテンツの合成や 色空間変換時には、 SDRコンテンツのHDR基準白を 203cd/m²に固定する必要があります [Rpt_BT.2408]。 これにより合成入力のHDR基準白レベルは 合成後の信号のHDR基準白レベルに合致します。

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

2.2. ヘッドルームの導入

HDRディスプレイが出力できるピーク 輝度レベルは 大きく異なります。

ピークホワイトがHDR基準白よりどれだけ高いかを HDRヘッドルームと呼び、 これはHDR基準白のレベルや ユーザーの好み、 また視聴条件に依存します。

ヘッドルームは通常、写真用語のストップで表されます。 このため、標準ダイナミックレンジ(SDR)は HDRヘッドルームが0ストップであり、 最も明るい白がHDR基準白となります。

例えば、 低価格帯HDRディスプレイ (DisplayHDR 400の要件をぎりぎり満たす Vesa Certified DisplayHDR認証の最下位グレード[DisplayHDR])では、 HDR基準白が最大200cd/m2、ピークホワイトが 400cd/m2で、HDRヘッドルームは1ストップしかありません。
例えば、ハイエンドHDRディスプレイ (DisplayHDR 1400の要件を超える 現在最高グレードのDisplayHDR認証ディスプレイ)では、 HDR基準白が最大400cd/m2、ピークホワイトが 1600cd/m2です。

暗い視聴環境で HDR基準白を100cd/m2に設定した場合、 HDRヘッドルームは4ストップ(16倍)になります。

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()>
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]。 これは、相対単位(白のY=1)から絶対単位(cd/m²、ニットとも呼ばれる)への変換です。 サンプルコード では、この定数を 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 でそのまま使われることに注意してください。

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は[0%, 100%]範囲の明度(HDR基準白に対する相対値)を使い、 Oklabも[0,1.0]範囲の明度(1.0がHDR基準白)を利用します。 これに対し、JzazbzのJz軸は[0,1.0]範囲ですが、 エンコード方式は パーセプチュアルクォンタイザー(PQ)に似ており、 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]は ICTCPをリニアBT.2100 RGB から変換して定義していますが、 変換はLMS経由であるため、他の色空間も XYZ→LMS変換を経て表現できます [What_is_ICtCp]サンプルコードもこの方法を使います。

この色は 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
この色はJzazbzでのsRGB色「lime」を表し、
 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 §  15. <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]

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〜104cd/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にした色は 輝度203cd/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 [Rpt_BT.2408] の表3・4も参照。

PQトランスファ関数を用いるHDRでは、 SDRのHDR基準白を PQ値58%で表示する輝度、203cd/m²と 同じ輝度にマッピングすべきです。[SMPTE-ST-2084]

ただし実装では、非基準視聴条件も考慮する色再レンダリング処理を含めても構いません。

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

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

このセクションは CSS Color 4 § 15.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 § 18 色変換のサンプルコードの すべての変換コードが利用可能であることを前提とします。

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 に設定することもできます。

変更点

変更点(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]
Chris Lilley; Tab Atkins Jr.; Lea Verou. CSS 色モジュール レベル 4. 2025年4月24日. CRD. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-5]
Chris Lilley; et al. CSS 色モジュール レベル 5. 2025年3月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. Cascading Style Sheets レベル 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]
ITU-R BT.2390-8 制作および国際番組交換におけるハイダイナミックレンジテレビ. 2020年2月. URL: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2390-8-2020-PDF-E.pdf
[RFC2119]
S. Bradner. 要件レベルを示すために RFC で使用するキーワード. 1997年3月. ベストカレントプラクティス. URL: https://datatracker.ietf.org/doc/html/rfc2119
[Rpt_BT.2408]
Report ITU-R BT.2408-0 HDR テレビ制作における運用手法. 2017年10月. URL: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-2017-PDF-E.pdf
[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)の開発と試験。In: 第6回 Color Imaging Conference 論文集, 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 テレビにおける色差の潜在的可視性評価のための客観指標. 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の赤・緑・青のエンコードを含む、他の例を追加する
他の例を追加する
同ページで定義されている黒レベルリフトΒを追加する?