0. 更新履歴
| 日付 | 内容 |
|---|---|
| 2024.07.30 | 公開 |
| 2024.07.31 | ・図3 のキャプションの誤記修正 ・3.5. に検証環境を追記 |
1. はじめに
本記事は前回の記事の続き(静止画編)である。
2. 目的
3. まとめ
3.1. Windows で現実的に利用可能な HDR対応の静止画フォーマットについて
ISO HDR と呼ばれる規格をサポートした静止画のフォーマットの代表例として HEIF, AVIF, PNG, JPEG XL がある[1]。 筆者の独断と偏見で Windows での利便性を調査したところ以下となった。
| フォーマット | Chrome/Edge での表示 | Lightroom からの Export | Affinity Photo 2 からの Export |
|---|---|---|---|
| HEIC | - | - | - |
| AVIF | ✓ | ✓ | - |
| PNG | ✓ | - | ✓ |
| JPEG XL | - | ✓ | - *1 |
上記の結果から筆者は AVIF または PNG が Windows での利用に適していると考える*2。
なお本記事では、筆者の開発環境(Linux)で評価用のカラーパッチを作成できた AVIF を使用して検証を行った*3。
3.2. 各種アプリケーションで AVIF を表示した際の挙動について
Windows 上のアプリケーションで AVIF の表示がどう加工されるか調べた。結果を以下に示す。
| アプリケーション | アプリケーションよって適用される加工の内容 |
|---|---|
| Chrome/Edge | ・SDR content brightness の設定に応じて明るさが変わる ・tone mapping が適用される |
| Lightroom | ・SDR content brightness の設定に応じて明るさが変わる ・clipping が適用される ・高輝度領域の彩度が落ちる |
| Adobe Camra Raw | ・SDR content brightness の設定に応じて明るさが変わる ・clipping が適用される ・高輝度領域の彩度が落ちる |
| Photoshop | - (HDR表示は非対応) |
| Affinity Photo 2 | - (AVIF は非対応) |
| Photos*4 | - (AVIF の HDR表示は非対応) |
SDR content brightness という設定値に応じて HDRコンテンツも明るさが変わる仕様となっていた 。 加えて Adobe製品では clipping と高輝度領域の彩度低下が起こっていた。
Chrome/Edge で明るさが変わってしまう様子を図1に、Lightroom で高輝度領域の彩度低下が起こる様子を図2に、Lightroom で clipping が適用される様子を図3 に示す。
|
|
|---|---|
| 図1. Chrome/Edge で表示した HDRコンテンツの明るさが変わってしまう様子 | 図2. Lightroom で HDRコンテンツを表示した際に高輝度領域の彩度が低下してしまう様子 |

3.3. 静止画の HDRコンテンツの加工を防ぐ方法
以下の 3条件を満たすことで、静止画の HDRコンテンツを殆ど加工せずにモニターへ出力することに成功した。
- 静止画表示のアプリケーションには Chrome/Edge を使う
- 前回の記事 と同様に 添付の MHC Profile*5 を Color Management 機能を使って設定する (図4)
- Windows の HDR設定で SDR content brightness を 31 に設定する (図5)
|
|
|---|---|
| 図4. モニターのスペックを偽装する MHC Profile を適用した様子 | 図5. SDR content brightness を 31 に設定した様子 |
なお「殆ど加工せずに」と表現した通り、ごく僅かに加工は行われてしまった。具体的には 204/203 = 1.0049 倍された*6。詳細は後述する。
3.4. 静止画の SDRの表示確認用に作成したページ
解析および効果確認用に以下の Webページを作成した*7。
3.5. 環境
検証に使用した環境を以下に記しておく。
| 項目 | 詳細 |
|---|---|
| OS | Windows 11 23H2 build 22631.3958 |
| CPU | AMD Ryzen 9 5950X |
| GPU | RTX 3070 (Studio Driver - 560.70) |
| Microsoft Edge | Version 127.0.2651.74 |
| Google Chrome | Version 127.0.6533.73 |
| Lightroom | Version 7.4.1 |
| Adobe Camera RAW | Version 16.4.0.1906 |
| Affinity Photo 2 | Version 2.5.3 |
4. 詳細
ここから先は冒頭のまとめに至るまでに筆者が調査した内容を述べていく。なお、以下の内容は Chrome/Edge について調査した内容となっている。 Lightroom、Adobe Camera Raw での細かい調査はしていない。ご容赦いただきたい*8。
4.1. HDR表示において動画と静止画は処理が異なる
はじめに筆者が衝撃を受けたことを述べておく。それは同じ輝度を持つコンテンツであっても、動画と静止画では表示用の処理が異なるという点である。具体例を図6 に示す。

図6 の上部はテストパターンを静止画の AVIF で表示したもの、下部は YouTube の動画として表示したものである。双方とも色空間は Rec.2100-PQ であり輝度情報は等しい。 しかし、右側の波形モニター表示を見ると輝度が異なっていることが分かる。後述する適切な設定を行わなければ、このように表示輝度に差異が生まれる状況となっている。
4.2. 静止画の HDR表示の内部処理について
それでは Chrome/Edge を例に、静止画の HDR表示について筆者が理解した点を述べていく。
筆者は調査を経て、静止画の HDR表示を理解することは、アプリケーション内部の SDR/HDR 合成処理を理解することと同じだと実感した。 そうした背景もあり、ここでは以下の順序で説明を行っていく。
Windows 内部の合成用カラースペースについて
はじめに Windows 内部の合成用カラースペースである scRGB について簡単に説明をしておく*9。
scRGB は、color primary は sRGB と同じでありつつも 1.0 を超える値や負の値をサポートすることで WCG や HDR をサポートした色空間である。 値は half float (FP16) の浮動小数点数で表現され、gamma は 1.0 の linear な空間となっている。
アプリケーションは SDRコンテンツと HDRコンテンツを scRGB にマッピングすることで合成処理を行う。
ここで重要なのは scRGB では (R, G, B) = (1.0, 1.0, 1.0) が 80 nits に紐づけられている点である[2]。 そのため scRGB では 100 nits や 1000 nits のパッチは (1.25, 1.25, 1.25) や (12.5, 12.5, 12.5) という値で表現される。
一般的には (R, G, B) = (1.0, 1.0, 1.0) は 100 nits を意味することが多いと思うので、ここは混乱を生じやすいポイントである。 こうした背景があり、以後に登場する数式には「80」という数字が登場する。注意して頂きたい。
SDR reference white について
続いて内部処理で重要な役割を果たす SDR reference white というパラメータについて説明する。
これは名前の通り「SDR の基準の白」の明るさを意味するパラメータであり、Windows では scRGB での明るさ調整に使われる。
Windows では System -> Display -> HDR -> SDR content brightness から設定できる(図7)。

SDR content brightness のスライダーは 0~100 まであり、スライダーを右に動かすと Windows 内部の SDR reference white の値が増加し、 画面が明るくなる仕様となっている。
SDR content brightness と SDR reference white の関係性を以下に示す。SDR reference white はスライダーの値に応じて 80~480 nits まで変化する。
| SDR content brightness | SDR reference white |
|---|---|
| 0 | 80 nits |
| 1 | 84 nits |
| 5 | 100 nits |
| 31 | 204 nits |
| 100 | 480 nits |
表から分かるように 1目盛りで 4 nits の変化が生じる。なお、上記の仕様はドキュメントが見つからなかったので自力で調べた。 詳細は本記事の「付録1」を参照。
SDR コンテンツの合成処理について
続いて SDRコンテンツの scRGB への合成処理について説明する。
これは非常にシンプルであり、SDRコンテンツは Windows のドキュメント 通りに SDR reference white の値に応じてスケールしてから scRGB に合成される[3]。
合成前の SDRコンテンツの輝度を 、合成語の輝度を
、SDR reference white を
とすると、
は以下の数式で計算できる。
なお、 の範囲は sRGB準拠で 0~80 nits である。
HDR コンテンツの輝度調整
本命の HDRコンテンツの scRGB への合成処理について説明する。 筆者がテストパターンを使い検証を繰り返した結果、次の事がわかった。
合成前の HDRコンテンツの絶対輝度を 、合成後の絶対輝度を
、SDR reference white を
とすると、
は以下の式で決まる。
ここで は tone mapping を行う関数を意味する。なお、具体的な数式は分からなかった。
ここでポイントは 3つある。
- ① 203 という数値で正規化が行われる
- ② 絶対輝度の HDRコンテンツも SDR reference white の影響を受ける
- ③ SDR reference white の値が大きくなると tone mapping が適用される
まず①について述べる。式から分かるように HDRコンテンツは 203 nits に対して正規化が行われる*10。 (1)式と(2)式を見比べると分かる通り、この処理で「SDRコンテンツの白輝度」と「HDRコンテンツの 203 nits」は同じ値となる。
具体例を Windows の HDRスクリーンショット機能*11を使って示す*12。なお、HDRスクリーンショット機能の詳細については本記事の「付録2」を参照して頂きたい。
さて、以下の図8、図9 は筆者が作成した 検証用ページ のカラーパッチの HDRスクリーンショットである(SDR contents brightness 設定は 0)。Nuke で開き Linear値を確認している様子している。
これを見ると HDRコンテンツ(図8)も SDRコンテンツ(図9)も共に (1.0, 1.0, 1.0) となっていることがわかる。
|
|
|---|---|
| 図8. 203 nits の AVIF パッチの値 | 図9. 背景の SDR の白色の値 |
続いて②について述べる。これは SDR reference white を変えた際の挙動を実際に見てもらうのが早い。 SDR reference white を 80 nits -> 100 nits に変えて同じように HDRスクリーンショットを確認した結果を図10、図11 に示す。
|
|
|---|---|
| 図10. 図8 の SDR reference white を 100 nits に変えたもの | 図11. 図9 の SDR reference white を 100 nits に変えたもの |
図10、図11 を見ればわかるように、SDR reference white が変わると SDRコンテンツの明るさだけでなく HDRコンテンツの明るさも変わることが分かる。
最後に③について述べる。SDR reference white は内部的に 480 nits まで設定可能だが、単純に SDR reference white でスケールした場合、SDR reference white が 203 nits を超えると高輝度領域に白飛びが生じてしまう。これを防ぐために tone mapping が適用される。筆者が解析した様子を図12 に示す。なお、具体的にどのような数式で tone mapping を行っているかは分からなかった。

以上の観察結果から筆者は HDRコンテンツは (2)式に従って scRGB に合成されると考えている。なお、厳密には Rec.2020色域から sRGB色域への変換も行われるのだが、本記事ではその辺りの詳細は割愛する。
4.3. 静止画の HDR表示でアプリケーション側の加工を防ぐ方法について
先ほどの (2)式 および 図12 を見れば分かると思うが、SDR reference white を 203 nits に設定すれば良い。 しかし、残念ながら SDR reference white は 4 nits 刻みでしか設定できない。そのため 204 nits に設定するのが加工を最小限に抑える方法となる。
SDR reference white を 204 nits にするには SDR content brightness を 31 に設定すれば良い。
ということで冒頭のまとめで述べた通り、アプリケーション側の加工を防ぐには以下の 3条件を満たせば良い。
- 静止画表示のアプリケーションには Chrome/Edge を使う
- 前回の記事 と同様に 添付の MHC Profile*13 を Color Management 機能を使って設定する
- Windows の HDR設定で SDR content brightness を 31 に設定する
5. 感想
HDR表示は複雑すぎるうぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅぅ!!!
その一方で、必死に調査したかいもあって Windows の内部処理については だいぶ理解が深まった。 この調子で次は DaVinci Resolve 19 の HDR表示について調査を行いたい。
付録1. SDR content brightness と SDR reference white の関係
SDR content brightness と SDR reference white の関係の詳細についてはドキュメントが見つからなかったため、筆者は自力で確認を行った。
Windows のドキュメント を参照するとデスクトップアプリケーションの場合、SDR reference white は DISPLAYCONFIG_SDR_WHITE_LEVEL 構造体 を参照することで確認できる。
そこで筆者は Windows の GUI から SDR content brightness を変化させつつ、DISPLAYCONFIG_SDR_WHITE_LEVEL の値を確認した。 ソースコードはリンク先 を参照して頂きたい*14。
こうして SDR content brightness と SDR reference white の関係を導きだした。筆者としては「30.75」という目盛りを用意して SDR reference white が 203 nits を選択可能にして欲しかった。
付録2. HDRスクリーンショットの撮影と Nuke/DaVinci Resolve で開くための OpenEXR 変換について
Windows で HDR が有効になっているとき、通常の手法を使ってスクリーンショットを撮影すると、得られるデータは SDR となってしまい HDRのスクリーンショットを撮影することができない。代替として Win+Alt+PrtScn キーを押下することで選択しているウィンドウの HDRスクリーンショットを撮影することができる。
なお、この HDRスクリーンショットには注意点が 2点ある。
①は気をつけるだけで良いが、②は筆者としてはかなり面倒であった。
調査したところ ②については Python にて imagecodecs と colour-science を使えば OpenEXR へと変換できることがわかった。そのため筆者は以下のようなコードを書いて JPEGXR to OpenEXR 変換をしてから画像解析を行った。
from imagecodecs import JPEGXR, imread
from colour.io import write_image # OpenImageIO も必要なので別途入れて下さい
def jpeg_xr_to_exr(src_fname="./Windows_HDR_Capture/600.jxr"):
if not JPEGXR.available:
print("JPEG XR is not supported")
return
dst_fname = src_fname.replace(".jxr", ".exr")
image = imread(src_fname)
write_image(image=image, path=dst_fname)
参考資料
[1] Apple, "WWDC24: Use HDR for dynamic image experiences in your app", https://youtu.be/5jP4j9d71i0?si=Ooso6INKL2_6DdZf&t=537
[2] Microsoft, "Use FP16 pixel format and scRGB color space", https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range#option-1-use-fp16-pixel-format-and-scrgb-color-space
[3] Microsoft, "Match your app's reference white to the OS SDR reference white level", https://learn.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range#match-your-apps-reference-white-to-the-os-sdr-reference-white-level
*2:あくまでも 2024年7月時点での話。今後はサポートするアプリケーションが増えて状況は変わっていくと推測する
*3:PNG は HDR用の CICPタグを埋め込んだカラーパッチの作成に失敗した…。正確には CICP の埋め込みには成功したのだが Chrome/Edge で HDRとして認識されなかった。
*5:モニターのスペックを、ピーク輝度: 10000 nits、Color primaries: BT.2020 に偽装するための ICC プロファイル
*6:加えてごく僅かに tone mapping も適用されていると推測する
*7:筆者に Webページを書くスキルはないので ChatGPT にお願いして HTML を書いてもらった
*8:軽く確認した感じだと概ね Chrome/Edge と似た挙動のようである
*9:なお、本記事を読んでいる方は「scRGB は Windows内部の話であって、Chrome/Edge などの各種アプリケーションの内部処理は別の色空間で行われるのでは?」と疑問を持つかもしれない。確かにその通りなのだが、説明が複雑になるため本記事では Chrome/Edge は内部で Windows と同じ scRGB を使って合成している、という前提で説明をしていく
*10:203 という数値は ITU-R BT.2408 の HDR Reference White から来ていると推測する
*11:「HDRスクリーンショット機能」という名称は筆者が勝手に読んでいる名称である。公式の名称が見つからなかったので本記事ではこの呼び方をする
*12:本質的にはこの検証もPCからの出力信号をキャプチャして確認すべきなのだが、203 という数値が本当に正しいかを確認するには HDMI のキャプチャだと誤差があり難しかったので変わりに HDRスクリーンショットを使った
*13:モニターのスペックを、ピーク輝度: 10000 nits、Color primaries: BT.2020 に偽装するための ICC プロファイル
*14:Chromium のコードを参考に ChatGPT 先生に作ってもらいました
*15:筆者がよく使う Nuke や DaVinci Resolve は対応していない







