toruのブログ

月1くらいで記事書きたい。

Davinci Resolve の Fusion ページのカラーマネジメントについて少し調べた

0. 更新履歴

日付 (YYYY/MM/DD) 内容
2023/1/14 新規作成
2023/1/16 4.4. DaVinci YRGB Color Managed の場合の DRT に関する補足を追記

1. 背景

  • 筆者は画像処理を行う場合に Python を使うことが多い
  • 簡単な処理の場合はコードを書かずに GUI で済ませたくなることもある
  • そうした場合 DaVinci Resolve の Fusionページが扱えると便利であるが、筆者は Fusionページのカラーマネジメントに関する知識が欠落していた
  • そのため少し調べてみることにした

2. 目的

  • Fusion ページのカラーマネジメントについて調べる
  • 具体的には以下の4点に関する理解を深める
    • DaVinci Resolve において Fusionページの画像処理はいつ行われるのか(Editページの後?)
    • Linear ⇔ Non-linear の変換がどのように行われるのか (自動で変換される?)
    • Linear 変換後の色域はどうなっているのか(ACES AP1固定?Timeline color space に変換?)
    • Linear 空間をモニター表示する際の View LUT はどうなっているのか

3. 結論

Fusion ページのカラーマネジメントについて理解した内容を以下に示す。

3.1. Fusionページの画像処理が行われるタイミングについて

DaVinci Resolve において Fusion ページの処理は 図1 の緑枠で示した箇所で行われることが分かった[1]。 Cut/Edit ページよりも手前で行われることに注意したい[2]。

図1. 全体の中で Fusionページの画像処理が行われる場所。図は公式マニュアルより借用 [1]

3.2. Linear ⇔ Non-linear の変換について

Fusionページで行うコンポジットの作業は Linear空間で行うため、Fusionページの前後で Linear ⇔ Non-linear の変換が必要である。 調べたところ、この変換はプロジェクト設定の Color science *1 の設定値によって異なることが分かった[3]。 まとめた結果を以下の表1 に示す。

表1. Linear ⇔ Non-linear 変換の方法
Color science 設定値 Linear化手順 利用するノードの例
DaVinci YRGB 作業者がノードを使い手動で変換 CineLog、Gamut、ColorSpaceTransform、
FileLUT、OCIOColorspace など
DaVinci YRGB Color Managed
ACEScc、ACEScct
Resolve が自動で変換 *2 -

3.3. Linear 変換後の色域について

色関連の処理を行う場合、Linear化後の色域がどうなっているか理解しておくことも重要である。 Linear変換後の色域に関して調査したところ、こちらもプロジェクト設定の Color science の値によって方法が異なることが分かった。 結果を以下の表2 に示す。

表2. Linear化後の色域の情報
Color science 設定値 Linear変換後の色域
DaVinci YRGB Linear化で使用したノードの設定に従う(作業者が決める)
DaVinci YRGB Color Managed Timeline color space となる
ACEScc、ACEScct ACES AP1 となる

3.4. Linear 空間をモニター表示する際の View LUT について

Fusionページの画像をプレビューするためには、画像処理を行う Linear 空間からモニター表示用の色空間へ変換が必須である。 Fusionページにはこれを実現するための機能として LUT menu があり、ここで View LUT を設定できる[3]。

LUT menu から View LUT を選択した結果についてもプロジェクト設定の Color science の値によって挙動が異なることが分かった。 結果を以下の表3 に示す。

表3. View LUT の選択について
Color science 設定値 View LUT について
DaVinci YRGB LUT menu から任意の項目を選択可能
DaVinci YRGB Color Managed
ACEScc、ACEScct
自動で sRGB への変換が適用される
Managed 以外の項目を選ぶと View LUT が2重がけになる <要出典 *3>

3.5. まとめ

ここまで述べた内容を図にまとめた結果を以下に示す。

図2. Fusion を含めた全体のカラマネについての筆者の理解まとめ

4. 補足

以下に補足情報を残す。

4.1. DaVinci Resolve の Color science 設定について

DaVinci Resolve には 4つの Color science 設定が存在する[4]。簡単な説明を表4 にまとめておく。

表4. Color science 設定の簡単な説明
Color science 設定 簡単な説明
DaVinci YRGB デフォルトの設定。色変換の設定は原則として制作者が手動で行う
DaVinci YRGB Color Managed RCM *4と呼ばれる Resolve 独自のカラマネが働く。ユーザーは Timeline color space と Output color space さえ設定すれば Resolve がいい感じにカラマネをしてくれる *5
ACEScc / ACEScct ACES workflow 用のカラマネが働く。
(筆者はガッツリと使った経験がなく細かいことは書けないです。すみません)

4.2. Linear 変換後の色域の確認方法

Linear 変換後の色域の調査は自作のテストパターンを使って行った。手順は以下の通りである。

  1. ARRI LogC4 / ARRI Wide Gamut 4 をターゲットとした Color Checker を含むテストパターンを作成 (図3)
  2. Color Checker の R, G, B のパッチを各種色域に変換した場合の RGB値を事前に計算 (表5)
  3. Fusionページ下部の Status Bar に表示される RGB値 (図4) と表5 の内容を比較して どの色域に変換されたかを判断

img1

図3 確認に使用したテストパターン

表5. Color Checker のR, G, B のパッチを各種色域に変換した結果

title R patch G patch B patch
P3D65 (0.38119, 0.04522, 0.04725) (0.09754, 0.29132, 0.08819) (0.02500, 0.05063, 0.26642)
BT.2020 (0.29859, 0.06062, 0.04681) (0.13558, 0.27992, 0.09176) (0.04157, 0.05215, 0.26291)
ACES AP0 *6 (0.21993, 0.07017, 0.04703) (0.15140, 0.25571, 0.09645) (0.07916, 0.07142, 0.25774)
ACES AP1 (0.29251, 0.06101, 0.04833) (0.13854, 0.27957, 0.09595) (0.04261, 0.05226, 0.25738)

図4. Fusionページで Green のパッチの RGB値を確認している様子

4.3. View LUT の確認に関する補足

表3 で紹介したように Color science が DaVinci YRGB Color Managed、ACEScc および ACEScct の場合は LUT menu で Managed を選択すると Resolve 側で勝手に sRGB への変換が行われる。 これをどう調査したのかを補足しておく。

やり方は単純で以下の手順を行っただけである。

  1. 図3 のテストパターンを sRGB に変換しておく (図6 参照)
  2. Fusionページで View LUT が適用された状態の画面のスクリーンショットを撮る (図7 参照)
  3. 図6 と図7 の Color Checker の RGB値を比較する

8-bit 精度で 1CV 程度のズレはあったが、sRGB 以外に変換されているようには思えなかったので sRGBに変換されていると断定した。

図6. sRGB に変換した図3のテストパターン 図7. Fusion ページで View LUT が適用された状態のスクリーンショット

4.4. DaVinci YRGB Color Managed の場合の DRT に関する補足

DaVinci Resolve には Ver.17 より DRT (Display Rendering Transform) と呼ばれる機能 が導入されている。 これは DaVinci YRGB Color Managed が有効な場合はデフォルトで有効となる機能である。

DRT が有効な場合はFusionページよりも手前で Tome mapping が適用されるため[5]、 Fusionページでの Linear変換後の値が純粋な Linear 値からズレてることになる。

無効化する場合は Project Settings で下図のように Input DRT を None に設定すること。

図8. Project Settings で Input DRT を無効化している様子

5. 感想

後から統合した機能ということもあり、Fusionページは EDITページや Colorページと比較すると カラーマネジメントに対する考え方が異なることが分かった。 しかし、テストパターンを使って変換後の値を注意深く観察することで、それなりに Fusionページのカラーマネジメントを理解できるようになった。 Fusionページが以前よりも親しく感じられるようになったと思っている。時間をかけて調べた価値はあった。

本記事では掘り下げなかったが View LUT 適用後の HDR表示が困難である点が個人的には気になった。 Fusionページを使った HDR表示については、また機会があれば挑戦してみたい。 *7

6. 参考資料

あまり良くない書き方だとは思うのですが、今回は同じドキュメントに対してページ番号を変えて参照する形をとっています。
将来的に公式マニュアルは公開が終わる可能性があるので、PDFのコピーを以下に貼っておきます。

DaVinci_Resolve_18_Reference_Manual.pdf - Google ドライブ

[1] Blackmagic Design, "December 2023 Reference Manual DaVinci Resolve 18.6", pp.3167-3169
[2] Blackmagic Design, "December 2023 Reference Manual DaVinci Resolve 18.6", p.1521
[3] Blackmagic Design, "December 2023 Reference Manual DaVinci Resolve 18.6", pp.1530-1542
[4] Blackmagic Design, "December 2023 Reference Manual DaVinci Resolve 18.6", p.140
[5] Blackmagic Design, "December 2023 Reference Manual DaVinci Resolve 18.6", pp.220-234

*1:Color science の概要については補足の「4.1. DaVinci Resolve の Color science 設定について」を参照

*2:DaVinci YRGB Color Managed の場合は Input DRT 設定を None にしないと理論通りの Linear値とならないので注意すること。補足を 4.4. に追記したので必要に応じて参照して頂きたい

*3:筆者の調査および Xで頂いた有識者のコメントにより2重がけとなるのは事実だが、それに言及している公式ドキュメントが見つからない

*4:Resolve Color Management の略称

*5:というのは理想であって実際はマニュアルで設定が必要な場合もある

*6:白色点は chromatic adaptation を使って D60 に変換した。AP1 も同様

*7:DeckLink の出力には View LUT が適用されない仕様っぽいが、デュアルモニター構成にして Clean Feed を有効にして表示すればワンチャン行ける予感はしている

Apple/Adobe の Gain Map HDR について調べて軽く実装をしてみた

1. 背景

  • Google の Pixel 8 にて Ultra HDR という静止画 の HDR 用の新フォーマットが導入された [1][2]
  • Pixel 8 を買った職場の同僚が HDR の写真を筆者に見せて自慢してきた
  • 筆者が所有している iPhone 15 Pro も静止画の HDR をサポートしているのだが、恥ずかしいことに動作原理について殆ど理解していなかった
  • このままでは負ける(誰に?)と思っため、iPhone が採用している静止画の HDRのフォーマットについて簡単な調査をすることにした

2. 目的

  • iPhone 15 Pro で使用されている静止画の HDRフォーマットについて調べる
  • 実際に実装して挙動を確認する

3. おことわり

本記事は Gain Map HDR の概要を理解することに注力しています。 そのため Gain Map HDR に関する全ての仕様を網羅的に説明することはしていません。 その点はご了承ください。

4. 結論

4.1. 静止画の HDR規格の種類に関する理解

  • 静止画の HDR フォーマットとして以下の3種類が存在することを理解した
    • Android 14 にてサポート開始となった Ultra HDR [1][2]
    • ISO/TS 22028-5 として国際標準になっている ISO HDR [3][4]
    • Apple/Adobe が ISO 化を進めている Gain Map HDR [5-7]

4.2. Gain Map HDR の仕様に関する理解

  • Gain Map HDR の仕様について以下を理解した
    • ① Gain Map と呼ばれる2次元のデータを用いることで環境光やモニタースペックに応じて動的に HDR画像を生成できる
      • 概要については図1を参照
    • ② Gain Map は SDR Rendition と HDR Rendition の差分を元に生成する *1
      • そのため事前に SDR Rendition と HDR Rendition の双方が完成している必要がある
    • ③ 動的に生成する HDR画像は Gain Map から計算するため SDR Rendition と HDR Rendition の中間画像となる
      • 計算式も決まっているため、画像ビューアによって頓珍漢な変換が行われることはない
      • 制作者は動的に生成される HDR画像の見た目を予想できる
    • ④ 動的な HDR画像の生成に関しては ウェイトパラメータ  W が非常に重要である
      •  W の計算時には HDR Capacity と呼ばれる、SDR White と HDR White の比から求まるパラメータを使用する
      • 制作者は Gain Map 用のメタデータを設定することで  W の挙動を制御できる
    • ⑤ Gain Map HDR は輝度方向の変換は行うが色度方向の変換は行わない
      • つまり Tone mapping には対応するが Gamut mapping には対応しない
    • ⑥ Gain Map HDR後方互換性を維持しつつ、多くの画像フォーマットで利用が可能である
      • JPEG/JPEG XL/HEIF/AVIF/TIFF/DNG に Gain Map の埋め込みが可能 *2
      • 後方互換性として Gain Map に対応していない画像ビューアでは SDR Rendition or HDR Rendition の表示が行われる

図1. Gain Map HDR の概要

  • Gain Map の生成処理および適用処理の全体像を理解した
    • 生成処理の概要を図2 に、適用処理の概要を図3 に示す
    • なお本記事で説明するのは図のオレンジ色の部分のみである。その他の詳細に関しては 仕様書 を参照して頂きたい

図2. Gain Map 生成処理の概要

図3. Gain Map 適用の概要

4.3. 実装の結果

実際の写真およびテストパターン画像に対して Gain Map を使い SDR 画像から HDR画像を生成した結果を以下に示す。


動画1. Gain Map を使い普通の写真を SDR から HDR に変換した様子

動画2. Gain Map を使いテストパターンを SDR から HDR に変換した様子
なお、右上のColorChecker は SDR Rendition と HDR Rendition で同じ輝度となるように Gain Map を作成してある

5. 結論に至るまでの経緯

本記事を書くにあたり筆者が学習した内容を以下に記していく。

最初に静止画用の HDR規格について簡単に述べ、その後に Gain Map HDR の仕様について述べていく。

5.1. 静止画向けの HDRの規格の簡単なまとめ

まず静止画の HDR規格について簡単にまとめておく。

静止画における HDR というと、以前は露出を変えて連続撮影したデータを合成することで「明るい部分と影の細部がきれいに表現された画像」を意味することが多かった[8]。 この画像には確かにハイダイナミックレンジの情報量は含まれるものの、表示は SDRレンジ のままであった。 別の言い方をすると HDRレンジの撮影データにトーンマッピングを適用し SDRレンジに変換したものであった。

その一方で、本記事で扱う静止画の HDR表示が HDRレンジ であるものを示す。 これはザックリと言うと既に動画で利用されている HDR の技術[9] を静止画に適用したものである。

さて、静止画の HDRフォーマットは大きく以下の2種類に分けられる。

  • 表示デバイスの性能や視聴環境に応じた補正を定義していないフォーマット
  • 表示デバイスの性能や視聴環境に応じた補正を定義しているフォーマット

前者に ISO HDR が、後者に Gain Map HDR と Ultra HDR がある。

ISO HDR とは CICP等を使って HDR の色空間を定義する静止画 HDRの 規格であり、ISO/TS 22028-5:2023 にて国際標準となっている。 動画でいうと HDR10 に近い。

Gain Map HDRUltra HDR は更に利便性を向上させ、表示デバイスの性能や視聴環境に応じた補正も可能にしたものである。 動画でいうと Dolby Vision や HDR10+ に近い。

以後、本記事では Gain Map HDR に注目して説明していく(Ultra HDR については残念ながら調査ができていないため言及しない)。

5.2. Gain Map HDR について筆者が理解した内容のまとめ

ここからは本題の Gain Map HDR について述べていく。

5.2.1 筆者の所感

はじめに所感を述べる。

細かい動作を確認していて分かったが、Gain Map HDR は筆者が以前より求めていたものに合致していた。 少し前に書いた JPEG XL の記事で筆者は以下の意見を書いた。

色々と試していて思ったが tone mapping, gamut mapping がやはり鬼門だと思う。HDR/WCG は表示デバイスごとに表示性能の差があまりにも大きくて、 一体全体どう変換するのが最適なのか未だに分からない。 様々な実装が提案されているが国際標準に至るものはなく、輝度や色度が制限されたモニターにおける「正しい HDR表示」をどう定義すれば良いのか本当に分からない。

このうち Tone mapping については Gain Map HDR が一つの解になっていると考えている。ということで筆者が理解した内容を以下にまとめていく。

5.2.2. Gain Map HDR の概要

まず Gain Map HDR について数式ベースで概要を説明する。

Gain Map は SDR Rendition と HDR Rendition の差分(比率)から作成する。Gain Map を  G と置くと以下の式で作成される。


 \displaystyle
\begin{aligned}
G &= \log_2\left( \frac{HDR + k_{hdr}}{SDR + k_{sdr}}\right)
\end{aligned}
\tag{1}


ここで  SDR, HDR はそれぞれ Linearスケールでの SDR Rendition の値、HDR Rendition の値を意味する。 また  k_{sdr}, k_{hdr} \log_2 の結果を安定させるための係数である。

(1)式を変換すると  G SDR HDR の関係は以下となることが分かる。


 \displaystyle
\begin{aligned}
HDR &= (SDR + k_{sdr}) \cdot 2^G - h_{hdr}\\
\end{aligned}
\tag{2}
 \displaystyle
\begin{aligned}
SDR &= (HDR + k_{hdr}) \cdot 2^{-G} - k_{sdr} \\
\end{aligned}
\tag{3}


さて (2)、(3)式を見ると分かるように Gain Map HDR では SDR Rendition から HDR Rendition を生成することも、 その逆に HDR Rendition から SDR Rendition を生成することもできる。 Gain Map HDR では Gain Map をかける元の画像を Base Rendition と呼ぶ。 上記の (2)式は SDR Rendition が、(3)式は HDR Rendition が Base Rendition となっている。

以後は説明の簡略化のため、Base Rendition を SDR Rendition に固定して 説明を行う。 なお、Gain Map HDR の仕様では Base Rendition を HDR Rendition とした運用も可能である。 詳細については 仕様書 を参照して頂きたい。

さて、改めて(2)式に注目する。 この数式では Gain Map を使って SDR Rendition から HDR Rendition を作ることはできるが、 SDR Rendition と HDR Rendition の中間 の Adapted HDR Rendition *3 は作成できない。

Gain Map HDR ではウェイト  W を用いることで Adapted HDR Rendition の作成を可能としている。  Wは以下のように Gain Map  G にかける形で適用する。


 \displaystyle
\begin{aligned}
HDR &= (SDR + k_{sdr}) \cdot 2^{G \cdot W} - h_{hdr}
\end{aligned}
\tag{4}


以上が Gain Map HDR の概要となる。以下で筆者が重要だと感じたウェイト  W について説明を続けていく。

5.2.3. ウェイト  W の詳細

ここでは (4)式で使用するウェイト  W の計算方法について説明する。  Wについて理解するためには、まず Gain Map HDR に登場する HDR Capacity の概念を理解する必要がある。

HDR Capacity とは HDR成分を表示可能なヘッドルームがどの程度あるかを数値で示したものである(ヘッドルームの概念については WWDC 2023 および WWDC 2021 の動画が参考になる[3][10] )。

HDR Capacity  H は以下の数式で計算できる。


 \displaystyle
\begin{aligned}
H &= \log_2 \left(\frac{HDR_{white}}{SDR_{white}}\right) \\
\end{aligned}
\tag{5}

ここで  SDR_{white}, HDR_{white} は画像を表示するデバイスの SDR White (Diffuse White) の輝度、ピーク輝度を意味する。

例としてピーク輝度が 600 nits と 1000 nits の表示デバイス H を何パターンか計算してみる。結果を以下の表に示す。

環境  SDR_{white} [nits]  HDR_{white} [nits]  H (HDR Capacity)
一般的な屋内 203 600 1.56
一般的な屋内 203 1000 2.30
暗い屋内 80 600 2.91
暗い屋内 80 1000 3.64
明るい屋外 400 600 0.58
明るい屋外 400 1000 1.00

このように HDR Capacity  H は表示デバイスのスペックや環境光の強さによって変化するパラメータである。 Gain Map HDR では  H を利用してウェイト  W を計算する。

さて (4)式を見ると分かるが  W は 0 ~ 1 の値が期待されているパラメータである。  W=0 の場合は生成される画像が SDR Rendition となり、 W=1 の場合は HDR Rendition となる。

ということで Gain Map HDR では  H を 0~1 に正規化してウェイト  W として用いる。 W の計算は以下の式で行う。

 \displaystyle
\begin{aligned}
W &= clamp \left(\frac{H - M_{lo}}{M_{hi} - M_{lo}}, 0, 1\right) \\
\end{aligned}
\tag{6}


ここで  M_{lo} M_{hi} はそれぞれ HDR Capacity の下限と上限を意味するパラメータであり、 制作者または制作ツールがメタデータとして Gain Map に付与するデータである。

説明が長くなったが、こうして HDR Capacity  H を正規化することでウェイト  W が得られる。

(6)式を見れば分かるように  M_{lo},  M_{hi} の設定は重要である。例として  M_{hi} の値による Adapted HDR Rendition の違いを動画2 に示す。


動画2. 表示デバイスの輝度を 203 ~ 10000 nits と変化させた際の  M\_{hi} による描画結果の違い
左側は  M\_{hi} = \log_2 (1000/203) = 2.30、右側は  M\_{hi} = \log_2 (10000/203) = 5.62

動画を見ると表示デバイスの輝度設定は同じなのに、左右で明るさが異なっていることが分かる。 これは、左側の画像は表示デバイスの輝度が 1,000 nits で  W=1 となるのに対して右側は 10,000 nits で  W=1 となるからである。

別の言い方をすると  M_{lo},  M_{hi} を適切に設定することにより、画像の制作者は表示デバイスHDR Capacity に応じたウェイト  W の変化を制御可能とも言える。 これは非常に画期的であり、例えば 400 nits のピーク輝度をもつデバイスに表示される Adapted HDR Rendition に対して 「白飛びが生じても良いので輝度優先で表示する」、「輝度は暗くなるが白飛びが生じないように表示する」といった点を制作者側がコントロール可能になる。 そのため、ビューアソフトによって意図しないトーンマップが適用されるのを防ぐことができる。

とはいえ、全ての制作者が適切に  M_{lo},  M_{hi} を設定するのは難しいと考える。実際のところは多くのシーンで制作ツールが自動で適切な値を設定すると考える。 あるいは  M_{lo} = \log_2 \left(\frac{203}{203}\right) = 0.0,  M_{hi} = \log_2 \left(\frac{1000}{203}\right) = 2.30 を決め打ちで指定した場合も大半の場合は適切な表示になると考える。 なぜならば動画ではこの設定が標準となっているからである。*4

5.3. Gain Map HDR に関するその他のポイント

Gain Map HDR の概要説明はこれまで述べた通りである。以下に追加で筆者がポイントだと感じた点を記載する。 なお、以下の文言は殆ど筆者のポエムのようなものなので読み飛ばしてもらって構わない。

5.3.1. Gain Map 生成時の SDR Rendition の輝度に関して

今回の筆者の実装では、Gain Map の計算前に SDR Rendition を 2.03倍する 処理を加えた。 これは ITU-R BT.2305 にて定義されている SDR 用の Reference White (100 nits) を ITU-R BT.2408-7 で定義されている HDR用の Reference White (203 nits) に変換するためである[12][13]。

というのも、筆者は Adapted HDR Rendition について以下のように考えていたからである。

  • Adapted HDR Rendition は HDRモードの表示デバイス *5で表示される
  •  W = 0 となった場合の SDR Rendition も HDRモードの表示デバイスで表示される
  • そのため SDR Rendition は 100 nits 基準ではなく 203 nits 基準として準備した上で Gain Map を作成するのが好ましい

なお、当然のことであるが 2.03倍の処理は Linear空間にて行った。

5.3.2. Gain Map 生成時の SDR Rendition および HDR Rendition の Color Gamut (色域) について

今回の筆者の実装では Gain Map 計算前の SDR Rendition および HDR Rendition の Color Gamut は事前に P3-D65 に変換しておいた。 一般的には SDR は BT.709色域、HDR は P3-D65 or BT.2020色域を使うことが多いが、Gain Map HDR は (4)式から分かるように色域の変換 (Gamut Mapping) を行わない からである。そのため今回は色域方向の変換について考慮せずに済むように P3-D65 色域に事前に変換を行った。

6. おわりに

本記事の内容とは全然関係が無いのですが、私は石川県に住んでおります。 ご存知の方も多いとは思いますが 2024年1月1日に能登半島にて地震が起こり、能登半島では甚大な被害が出ています。

私自身は家屋も身体も無事であり何不自由なく過ごせておりますが、被災地の復興には多くの支援が必要だと考えております。 もしも可能であれば何らかの形で支援をして頂けると助かります。以下に支援用のリンクを記載しました。 内容をよく確認の上、余力のある方がいればご協力をお願いいたします。

7. 参考資料

[1] Android Open Source Project, "Ultra HDR", https://source.android.com/docs/core/camera/ultra-hdr
[2] Android Police, "Hands-on with Ultra HDR in Android 14: The future of photography", https://www.androidpolice.com/android-14-ultra-hdr-hands-on/
[3] Apple Developer, "Support HDR images in your app - WWDC23", https://developer.apple.com/videos/play/wwdc2023/10181
[4] ISO/TS 22028-5:2023, "Photography and graphic technology - Extended colour encodings for digital image storage, manipulation and interchange - Part 5: High dynamic range and wide colour gamut encoding for still images (HDR/WCG)", https://www.iso.org/standard/81863.html
[5] Adobe, "Gain Map Specification (1.0 draft 14, October 2023)", https://helpx.adobe.com/camera-raw/using/gain-map.html https://helpx.adobe.com/content/dam/help/en/camera-raw/using/gain-map/jcr_content/root/content/flex/items/position/position-par/table/row-io13dug-column-4a63daf/download_section/download-1/Gain_Map_1_0d14.pdf
[6] IS&T Electronic Imaging (EI) Symposium, "EI 2023 Plenary 2: Embedded Gain Maps for Adaptive Display of High Dynamic Range Images", https://youtu.be/HBVBLV9KZNI?si=iz7Z1Px1EjQtD6zu
[7] ISO/WD 21496-1, "Digital Photography - Gain map metadata for image conversion - Part 1: Dynamic Range Conversion", https://www.iso.org/standard/86775.html
[8] Apple サポート (日本), "iPhoneHDRカメラ", https://support.apple.com/ja-jp/guide/iphone/iph2cafe2ebc/12.0/ios/12.0
[9] Wikipedia, "High-dynamic-range television", https://en.wikipedia.org/wiki/High-dynamic-range_television
[10] Apple Developer, "Explore EDR on iOS", https://developer.apple.com/videos/play/wwdc2022/10113/?time=364
[11] ITU-R BT.2100-2, "Image parameter values for high dynamic range television for use in production and international programme exchange", https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2100-2-201807-I!!PDF-E.pdf
[12] ITU-R BT.2408-7, "Guidance for operational practices in HDR television production", https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-7-2023-PDF-E.pdf
[13] ITU-R BT.2305, "A reference viewing environment for evaluation of HDTV program material or completed programmes", https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2035-0-201307-I!!PDF-E.pdf

*1:SDR Rendition, HDR Rendition という表現は Gain Map の仕様書に従ったものである。日本語だと SDRマスター、HDRマスターという言い方が合うと筆者は考える

*2:その一方で今後に全てのファイルフォーマットで Gain Map HDR が運用されるかは不透明。現時点では「技術的に可能」くらいの理解が良いかもしれない

*3:Adapted HDR Rendition という表現は Ultra HDR の Specification から拝借した呼び方である。Gain Map HDR の仕様書では固有名称が与えられておらず、本記事で扱いづらかったため名前を与えた

*4:ITU-R BT.2100-2 の Table 3 の Peak luminance of display および ITU-R BT.2408-7 の Table 1 の HDR Reference White を参照 [11][12]

*5:HDRモードとは Reference White が 100 nits ではなく 203 nits となっている状態を意味する

DaVinci Resolve を使って Apple Log の特性を調べてみた

1. 背景

  • 筆者は iPhone 15 Pro MAX を購入した
  • iPhone 15 では Blackmagic Cam App を使うことで Apple Log を使った HDR撮影が可能である
  • 筆者はウキウキでテスト撮影をしたのだが、撮影中のモニター表示は Log のままであり露出調整が困難だった
  • そこで EL Zone System [1] を参考に露出調整用の View LUT を作成しようと考えた
  • しかし残念なことに Apple Log の特性は一般公開されていないため View LUT が作成できない状況にあった
  • View LUT を作らずに撮影を行うことは困難だったため DaVinci Resolve を使って Apple Log の特性を調査することにした

2. 目的

  • Apple Log の Encode/Decode の特性を調べる
  • Apple Log の色域を調べる
  • 得られた特性を利用して撮影時の露出調整用の View LUT を作成する

3. 結論

Apple Log の Encode/Decode の特性

DaVinci Resolve を使うことで Apple Log の特性を得ることに成功した。 Apple Log 単体の Encoding Function (OETF) の特性を図1に、他の Encoding Function との比較を図2に示す。

図1. Apple Log の特性 図2. 様々な Log Encoding との比較
Apple Log の色域

DaVinci Resolve を使うことで Apple Log の色域が Rec.2020 であることが分かった。

撮影時の露出調整用の View LUT の作成

得られた Apple Log の特性を利用して露出調整用の View LUT を作成することに成功した。撮影に使用した様子を動画1 に示す。


動画1. 撮影用に EL Zone System を用いた Apple Log 用の View LUT を適用した様子

4. 結論に至るまでの経緯

4.1. 作業環境

今回、筆者が作業を行った環境は以下の通りである。

名称 Version
Python 関連 リンク先pip listの結果参照 ()
iPhone iPhone 15 Pro Max
iOS 17.0.3
Blackmagic Cam 1.1.00029

ちゃんと確認したら自前でコンパイルしたライブラリはリストに表示されてなかったですね…

4.2. Apple Log の Encoding Function の調査

実は筆者は Resolve を利用した Cmera Log の特性調査を 4年前に一度行ったことがあった。そのため今回も同様の考え方を用いて調査を行った。

trev16.hatenablog.com

おおまかな確認手順は以下の通りである。

  1. Resolve に読み込むテストパターン画像の作成
  2. Resolve を使いテストパターンに対して Apple Log の Encoding Function を適用し EXR形式で保存
  3. EXRファイルから Apple Log の Encoding Function を実現する 1DLUT を作成
  4. 1DLUT を使い Apple Log の特性をプロット
4.2.1. Resolve に読み込むテストパターン画像の作成

まず Resolve への入力となる Log2 スケールの Ramp パターン画像を作成した。 ここで Log2 スケールとは水平方向に Log2 の空間で等間隔になるスケールを意味する。

例として 0~16 までを Log2 で刻んだ結果を以下に示す(比較対象として Linearスケールも併記した)。

# Log2 Scale
[ 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16 ]

# Linear Scale
[ 0, 2, 4, 6, 8, 10, 12, 14, 16 ]

画像の作成には以下のようなコードを使用した(別途 OpenImageIO が必要かも?)。

import numpy as np
from colour.io import write_image

def create_test_pattern_for_apple_log_encoding_analysis():
    width = 1920
    height = 1080
    ref_val = 0.18
    exp_range = 12

    def create_log2_x_scale(
            sample_num=32, ref_val=1.0, min_exposure=-6.5, max_exposure=6.5):
        x_min = np.log2(ref_val * (2 ** min_exposure))
        x_max = np.log2(ref_val * (2 ** max_exposure))
        x = np.linspace(x_min, x_max, sample_num)
        return 2.0 ** x

    def h_mono_line_to_img(line, height):
        return line.reshape(1, -1, 1).repeat(3, axis=2).repeat(height, axis=0)

    x = create_log2_x_scale(
        sample_num=width, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    img = h_mono_line_to_img(x, height)
    fname = f"./img/src_log2_-{exp_range}_to_{exp_range}_stops.exr"
    print(fname)
    write_image(img, fname)
4.2.2. Resolve を使いテストパターンに対して Apple Log の Encoding Function を適用し EXR形式で保存

生成した画像は前述のコードを見ればわかるように Linear データである。これを Resolve を使って Apple Log に変換した。 Resolve の Color Management 設定を図3 の通りに設定し、Apple Log に変換して EXR 形式で出力した (図4)。

図3. Color Management の設定 図4. 出力設定
4.2.3. EXRファイルから Apple Log の Encoding Function を実現する 1DLUT を作成

Resolve から出力された画像は Log2 スケール上の Linear データを Apple Log で Encode したデータ列 である。 そのため、このデータ列は Shaper を適用済みの 1DLUT とみなすことができる。

ということで、今回は このデータ列を Apple Log の Encoding function を得るための 1DLUT として利用した。 具体的には以下のようなコードを準備して Apple Log の Encoding function を実現した。

import numpy as np
from colour.utilities import tstack
from colour.io import read_image

def save_apple_log_as_1dlut():
    resolve_out_exr= "./secret/apple_log_encode_out.exr"
    img = read_image(resolve_out_exr)
    width = img.shape[1]
    ref_val = 0.18
    exp_range = 12

    x = create_log2_x_scale(
        sample_num=width, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    y = img[0, ..., 1]  # extract horizontal green line data 
    lut = tstack([x, y])
    np.save("./secret/apple_log_encode_lut.npy", lut)

def log_encoding_apple_log(x):
    """
    Scence linear to Apple Log.

    Parameters
    ----------
    x : ndarray
        Scene linear light (1.0 is SDR diffuse white)

    Examples
    --------
    >>> log_encoding_apple_log(0.18)
    0.488271418052

    Note
    ----
    Valid range of `x` is from 2^-12 to 2^12
    """
    lut_1d = np.load("./secret/apple_log_encode_lut.npy")
    y = np.interp(x, xp=lut_1d[..., 0], fp=lut_1d[..., 1])

    return y

簡単に説明すると log_encoding_apple_log をコールすると save_apple_log_as_1dlut にて作成した 1DLUT を参照し、 np.interp を使って LUT から Apple Log の値を得る仕組みになっている。

以上により Apple Log の Encoding Function を得ることができた。

4.2.4. 1DLUT を使い Apple Log の特性をプロット

作成した log_encoding_apple_log を使い、以下のようなコードを用いて特性をプロットした。 結果は冒頭の図1、図2 を参照…なのだが見やすいように以下にも再掲しておく。

import matplotlib.pyplot as plt

def plot_apple_log_for_blog():
    x = create_log2_x_scale(
            sample_num=32, ref_val=0.18,
            min_exposure=-12, max_exposure=12)
    apple_log = log_encoding_apple_log(x)
    x_plot = x / 0.18  # To set 18% grey to 0.0 on a Log2 scale
    fig = plt.figure(figsize=(10, 6))
    ax = fig.add_subplot(111)
    ax.set_xscale('log', base=2)
    ax.plot(x_plot, apple_log, '-o')
    plt.show()


図1 (再掲) Apple Log の特性 図2 (再掲) 様々な Log Encoding との比較

図を見ると、Apple Log は S-Log3 や LogC4 などのシネマカメラで使用される Camera Log と比較すると 収録可能なダイナミックレンジが狭いことがわかる (携帯用デバイスの Log なので実運用上は全く問題はないだろうが)。

4.3. Apple Log の Decoding Function の調査

Encoding Function の逆の作業を行っただけなので省略。

4.4. Apple Log の色域の調査

Apple Log の色域に関しても Resolve を使うことで簡単に調べることができた。 色々とやり方はあるのだが、ここでは Video Scope にある CIE Chromaticity を使った確認方法を紹介する。

やり方は非常に簡単で、Color Management 設定で Output color space に Apple Log を指定した状態で Video Scope を CIE Chromaticity に変更するだけである。すると現在の Output color space の色域が右上に表示される (図5 の② を参照)

図5. CIE Chromaticity を使って色域を確認している様子

ということで Apple Log の色域は Rec.2020 であることが分かった。

4.5. Apple Log 用の撮影補助用 View LUT の作成

ここまでの内容により Apple Log の特性を理解することができた。ここから Apple Log 用の View LUT 作成の話をしていく。

4.5.1. そもそも View LUT が必要になった理由について

初めに View LUT が必要となった理由を簡単に述べておく。

iPhone 15 Pro で動作する Blackmagic Cam App は Color Space に「Apple Log - HDR」を指定した場合、以下の図6 のような表示となる。 これは SDRモードで表示している iPhone のディスプレイに Apple Log が表示される形となっており、 自分のような素人にとっては露出調整が極めて困難であった。

図6. Apple Log が SDRレンジにマッピングされて表示される様子

一応、Blackmagic Cam App には標準でフォルスカラー表示も用意されていたのだが、 Apple Log の Code Value の 0~100% に対して色付けをする仕様となっており、やはり自分のような素人には扱いが困難であった。

そこで今回は EL Zone System を利用した View LUT を自作して適用することにした。

4.5.2. EL Zone System の概要および本記事での実装方針

ここで EL Zone System について補足説明しておく。EL Zone System は Webページ を見ると分かるように Linear値の 18% Gray を基準したフォルスカラー表示を行う技術である。 そのため Log Encoding の特性に依らず、HLG でも S-Log3 でも LogC4 でも一貫したフォルスカラー表示が可能となる素晴らしい技術である。

当然、Apple Log に関しても Decoding Function の特性が分かっていれば利用可能である。 しかし EL Zone System は詳細仕様が公開されていないため、今回は筆者の独自解釈による実装を行うことにした (そのため作成した View LUT は非公開とする)。

4.5.3. View LUT の作成および動作確認

ということで、以下で EL Zone System を用いた View LUT の生成方法および動作確認の方法について述べていく。

View LUT は 65x65x65 の 3DLUT として作成した。アルゴリズムの説明は非常に簡単なので省略する。 生成用のサンプルコードは リンク先に掲載した。興味のある方は確認して頂きたい。

続いて作成した View LUT の動作確認を行った。 動作確認用に「水平方向に Log2 スケールで増加する Scene Linear Light」を「Apple Log で Encode」したテストパターンを作成し、 Resolve 上でテストパターンに View LUT を適用して 18% Grey基準のフォルスカラー表示となるか確認した。

テストパターンの生成コードを以下に、テストパターンの様子を図7に、Resolve上で View LUT を適用した結果を図8 に示す。

def create_tp_for_verify_el_zone_system_lut_apple_log():
    width = 1920
    height = 1080
    num_of_sample = width
    ref_val = 0.18
    exp_range = 8
    x = create_log2_x_scale(
        sample_num=num_of_sample, ref_val=ref_val,
        min_exposure=-exp_range, max_exposure=exp_range)
    y = log_encoding_apple_log(x)
    img = h_mono_line_to_img(y, height)
    fname = "./img/src_apple_log_log2_"
    fname += f"-{exp_range}_to_{exp_range}_stops.exr"
    print(fname)
    write_image(img, fname)


図7. テストパターンの見た目 図8. テストパターンに View LUT を適用した様子

今回、このテストパターンは 18% Grey 基準で -8 stops ~ +8 stops のレンジで作成した。 そのため EL Zone System の黒色~白色までの 17色が等間隔で表示されれば良い (-0.5, 0.0, +0.5 stops は 1/2 の間隔)。

右端が白色 (Over Exposed) にならずに 16色表示となってしまっているが、 これは 図1 を見ればわかるように Apple Log が +6 Stops までのレンジしかないことが原因である。よって問題ではない。

よって図8 の結果から View LUT は狙い通りに作成できたと判断した。

作成した View LUT は iPhone 15 Pro にコピーを行い、Blackmagic Cam で読み込んで View LUT として使用した。 実際に適用している様子が冒頭の動画である。こちらの動画も以下に再掲しておく。


動画1. 撮影用に EL Zone System を用いた Apple Log 用の View LUT を適用した様子

4.6. ソースコード

確認に使用したソースコード一式は以下にある。例によって筆者の環境でないと正常に動作しないと思われるが、参考データとして提供する。

github.com

5. 感想

筆者の知的好奇心は満たされた。満足した。

次は Gain Map HDR について調査してまとめる予定である(スペクトルの勉強はどうした?センサーも買ったのに全然使ってないぞ??)。

6. 参考資料

[1] Cinecam Inc. "EL Zone System", https://www.elzonesystem.com/

JPEG XL のHDR画像を作成し iPad の Safari 17 で HDR表示を試した

1. 背景

  • 2023年9月にリリース予定の Safari 17 の Beta Release Notes を確認すると「Added support for JPEG XL」の記述があった[1]
  • JPEG XL は BT.2100 PQ や BT.2100 HLG などの HDRの色空間をサポートした画像フォーマットである
  • そのため筆者は「iPhoneiPad で簡単に静止画の HDR表示が試せるのでは?」と考えた
  • そこで実際に試すことにした

2. 目的

  • HDR画像を JPEG XL形式で作成する
  • 併せて JPEG XL における色空間に関するパラメータを調査する
  • 作成した JPEG XL ファイルを使い iPadSafari 17 Beta で HDR表示を試す

3. 結論

  • BT.2100 PQ や BT.2100 HLG などの HDRの色空間の画像ファイルの生成に成功した
    • 作成したファイルは リンク先 からダウンロード可能
  • JPEG XL における色空間に関するパラメータとして以下の存在を確認した
    • color_space,white_point,primaries,rendering_intent,transfer_function
    • intensity_target,min_nits,linear_below
  • 第5世代 iPad Pro を使い Safari 17 Beta にて JPEG XL の HDR表示を試したが失敗した
    • 画像には HDR to SDR 変換が適用されてしまい SDR表示となった
    • iPadOS の Safari 17 は JPEG XLフォーマットには対応するが HDR表示は非サポートのようである (※1)

※1 筆者は macOSSafari 17 は HDR表示をサポートすると予想しているが、手元に macOS の機材が無いため未確認である

確認に使用した機材やツールのバージョンは以下の通りである。

機材 or ツール名 バージョン
iPad Pro 12.9-inch, 5th generation
iPadOS 17.0 Beta (21A5326a)
libjxl (JPEG XL のライブラリ) v0.9.0 ff8a9c1c

4. 詳細

4.1. JPEG XL フォーマットについて

全体概要に関しては libjxl の JPEG XL Format Overview を参照。

カラーマネジメントの概要に関しては libjxl の Color Management を参照。

4.2. HDR画像を JPEG XL フォーマットで保存する方法

筆者は PNG 形式の HDR画像をcjxlコマンドで JPEG XL形式に変換することで実現した。具体的な手順を以下に示す。

まず JPEG XL のリファレンス実装である libjxl をビルドした (※2)。 次にビルドで生成したcjxlを使い事前に作成した PNG画像を JPEG XL形式に変換した。その際に-x color_spaceオプションを使用して HDRに関するパラメータを指定した[2][3] (※3)。

cjxlコマンドを使った具体例を以下に示す。以下の例では BT.2100-HLG、BT.2100-PQ、P3D65-PQ の3種類の HDR画像を生成している。

# BT.2100-HLG
cjxl BT2100_HLG.png BT2100_HLG.jxl -x color_space=RGB_D65_202_Rel_HLG

# BT.2100-PQ
cjxl BT2100_PQ.png BT2100_HLG.jxl -x color_space=RGB_D65_202_Rel_PeQ

# P3D65-PQ (ST 2084)
cjxl P3D65_PQ.png P3D65_PQ.jxl -x color_space=RGB_D65_DCI_Rel_PeQ

ここで -x color_spaceオプションについて補足をする。指定するRGB_D65_202_Rel_HLGRGB_D65_202_Rel_PeQといった文字列は色空間に関するパラメータを並べたものである。 左からそれぞれcolor_space,white_point,primaries,rendering_intent,transfer_functionを意味する。これらに関しては次節で詳しく述べる。

cjxlコマンドで正しく HDR画像が生成できたかは jxlinfoコマンドで確認できる。動作例は 付録1 を参照。 また cjxlコマンドの その他のオプションに関しては 付録2 を参照して頂きたい。

※2 ビルドが面倒であれば公式がリリースしている ビルド済みバイナリ を使っても良い
※3 静止画では ICC Profile を使って色空間の指定をするのが一般的だが、現行の ICC v4 では HDR空間を正しく扱えないため CICP を使用している。CICPに関しては AVIF の過去記事 を参照

4.3. JPEG XL における色空間に関するパラメータの調査結果

調査の結果 8種類のパラメータの存在を確認した。各パラメータの意味を以下の表に示す。 加えて-x color_spaceオプションで指定可能な3文字のパラメータに関しても ソースコードを参考に 実際の値との対応関係を記載した[4]。

パラメータ名 説明 -x color_spaceオプションでの3文字表記との関係[4]
color_space 色空間。RGB, XYB など RGB: RGB
Gra: Gray
XYB: XYB
CS?: Unknown
white_point 白色点。D65, DCI-P3 など D65: D65
Cst: Custom
EER: E光源の白色点
DCI: DCI-P3
primaries 色域。sRGB, BT.2020 など SRG: sRGB
202: BT.2020
DCI: DCI-P3
Cst: Custom
transfer_function OETF。PQ, HLG など SRG: sRGB
Lin: Linear
709: BT.709
PeQ: PQ (ST 2084)
HLG: HLG
DCI: Gamma 2.6
TF?: Unknown
rendering_intent Rendering intent。
詳細は ICC の Specification 参照
Per: Perceptual
Rel: Relative
Sat: Saturation
Abs: Absolute
intensity_target 画像内の輝度レベルの上限値を
nits で示したもの[5]
-
min_nits 画像内の輝度レベルの下限値を
示したもの[5]
-
linear_below tome mapping の実行時に
変更を加えない上限の輝度レベル[5]
-

なお、2023年9月9日の時点では min_nits, linear_below の値をcjxlコマンドで設定できなかった(筆者はソースコードの初期値を変えてリビルドすることで対応した)。 また、後半の 3変数intensity_target, min_nits, linear_belowがデコード時の画面描画時に必ず参照されるのかは不明である (ISO/IEC 18181 を読めば分かるのかもしれないが筆者には購入するほどのモチベは無かった…)。

4.4. iPadSafari 17 での表示確認

作成した JPEG XLファイルを iPadOS 17 Beta の Safari 17 Beta にて表示した。確認に使用した画像の一覧を以下の表に示す。

結果は冒頭で述べた通り HDR表示はできなかった。一方で HDR to SDR 変換は働いており、画像データに埋め込んだ色情報は正しく認識されているようである(HLGの結果がかなり怪しいが…)。 なお、作成した JPEG XL データが本当に HDR表示に対応したものかは、別途 Adobe Camera Raw を使って確認済みである(詳細は省略)。

Primaries, Transfer function JPEG XL (対応ブラウザで確認下さい[6]) 参考としての PNG (カラマネ無し)
BT.709, sRGB srgb_xl srgb_png
BT.709, BT.709 (※4) 709_xl 709_png
DCI-P3, PQ p3pq_xl p32084
BT.20020, PQ 2100pq_xl 2020_pq
BT.2020, HLG (※5) hlg_xl hlg_png

※4 モニター側の EOTF が BT.1886 であると想定し画像データは Gamma 1/2.4 の OETF でエンコードした
※5 モニター側の OOTF (Gamma = 1.2) が適用された場合に適切な色となるよう事前に画像データへ Inverse OOTF を適用した

5. 感想

この記事を通じて AVIF に続き JPEG XL に関しても HDRの画像を生成できるようになった。

色々と試していて思ったが tone mapping, gamut mapping がやはり鬼門だと思う。HDR/WCG は表示デバイスごとに表示性能の差があまりにも大きくて、 一体全体どう変換するのが最適なのか未だに分からない。

様々な実装が提案されているが国際標準に至るものはなく、輝度や色度が制限されたモニターにおける「正しい HDR表示」をどう定義すれば良いのか本当に分からない。 一方で、この分野における技術的な興味は尽きてないので引き続き色々と最新情報を確認していきたい(全然確認が追いついていないが…)。

6. 付録

6.1. 付録1 jxlinfoコマンドの紹介

JPEG XL ファイルの色空間に関する情報を調べるにはjxlinfoが便利である(libjxl をビルドすると生成される)。

例として jxlinfo ./img/D65_202_PeQ.jxl を実行した際の具体的な出力を以下に示す。

JPEG XL file format container (ISO/IEC 18181-2)
JPEG XL image, 1920x1080, (possibly) lossless, 16-bit RGB
intensity_target: 10000.000000 nits
min_nits: 0.000000
relative_to_max_display: 0
linear_below: 0.000000
Color space: RGB, D65, Rec.2100 primaries, PQ transfer function, rendering intent: Relative

6.2. 付録2 cjxlコマンドの Usage

参考情報として cjxl -v コマンドの実行結果を以下に添付する。

JPEG XL encoder v0.9.0 ff8a9c1c [AVX2,SSE4,SSE2]
Usage: cjxl INPUT OUTPUT [OPTIONS...]
 INPUT
    the input can be PNG, APNG, GIF, JPEG, EXR, PPM, PFM, PAM, PGX, or JXL
 OUTPUT
    the compressed JXL output file

Basic options:
 -d DISTANCE, --distance=DISTANCE
    Target visual distance in JND units, lower = higher quality.
    0.0 = mathematically lossless. Default for already-lossy input (JPEG/GIF).
    1.0 = visually lossless. Default for other input.
    Recommended range: 0.5 .. 3.0. Allowed range: 0.0 ... 25.0. Mutually exclusive with --quality.
 -q QUALITY, --quality=QUALITY
    Quality setting, higher value = higher quality. This is internally mapped to --distance.
    100 = mathematically lossless. 90 = visually lossless.
    Quality values roughly match libjpeg quality.
    Recommended range: 68 .. 96. Allowed range: 0 .. 100. Mutually exclusive with --distance.
 -e EFFORT, --effort=EFFORT
    Encoder effort setting. Range: 1 .. 9.
    Default: 7. Higher numbers allow more computation at the expense of time.
    For lossless, generally it will produce smaller files.
    For lossy, higher effort should more accurately reach the target quality.
 -V, --version
    Print encoder library version number and exit.
 --quiet
    Be more silent
 -v, --verbose
    Verbose output; can be repeated and also applies to help (!).

Advanced options:
 -a A_DISTANCE, --alpha_distance=A_DISTANCE
    Target visual distance for the alpha channel, lower = higher quality.
    0.0 = mathematically lossless. 1.0 = visually lossless.
    Default is to use the same value as for the color image.
    Recommended range: 0.5 .. 3.0. Allowed range: 0.0 ... 25.0.
 -p, --progressive
    Enable (more) progressive/responsive decoding.
 --group_order=0|1
    Order in which 256x256 groups are stored in the codestream for progressive rendering.
    0 = scanline order, 1 = center-first order. Default: 0.
 --container=0|1
    0 = Avoid the container format unless it is needed (default)
    1 = Force using the container format even if it is not needed.
 --compress_boxes=0|1
    Disable/enable Brotli compression for metadata boxes. Default is 1 (enabled).
 --brotli_effort=B_EFFORT
    Brotli effort setting. Range: 0 .. 11.
    Default: 9. Higher number is more effort (slower).
 -m 0|1, --modular=0|1
    Use modular mode (default = encoder chooses, 0 = enforce VarDCT, 1 = enforce modular mode).
 -j 0|1, --lossless_jpeg=0|1
    If the input is JPEG, losslessly transcode JPEG, rather than using reencode pixels.
 --num_threads=N
    Number of worker threads (-1 == use machine default, 0 == do not use multithreading).
 --photon_noise_iso=ISO_FILM_SPEED
    Adds noise to the image emulating photographic film or sensor noise.
    Higher number = grainier image, e.g. 100 gives a low amount of noise,
    3200 gives a lot of noise. Default is 0.
 --intensity_target=N
    Upper bound on the intensity level present in the image, in nits.
    Default is 0, which means 'choose a sensible default value based on the color encoding.
 -x key=value, --dec-hints=key=value
    This is useful for 'raw' formats like PPM that cannot store colorspace information
    and metadata, or to strip or modify metadata in formats that do.
    The key 'color_space' indicates an enumerated ColorEncoding, for example:
      -x color_space=RGB_D65_SRG_Per_SRG is sRGB with perceptual rendering intent
      -x color_space=RGB_D65_202_Rel_PeQ is Rec.2100 PQ with relative rendering intent
    The key 'icc_pathname' refers to a binary file containing an ICC profile.
    The keys 'exif', 'xmp', and 'jumbf' refer to a binary file containing metadata;
    existing metadata of the same type will be overwritten.
    Specific metadata can be stripped using e.g. -x strip=exif

 -h, --help
    Prints this help message. Add -v (up to a total of 4 times) to see more options.

7. 参考資料

[1] Apple Developer Documentation, "Safari 17 Beta Release Notes", https://developer.apple.com/documentation/safari-release-notes/safari-17-release-notes

[2] libjxl/libjxl, "libjxl/doc/color_management.md", https://github.com/libjxl/libjxl/blob/main/doc/color_management.md

[3] libjxl/libjxl, "libjxl/tools/cjxl_main.cc", https://github.com/libjxl/libjxl/blob/ff8a9c1c/tools/cjxl_main.cc#L215-L232

[4] libjxl/libjxl, "libjxl/lib/jxl/color_encoding_internal.cc", https://github.com/libjxl/libjxl/blob/ff8a9c1c/lib/jxl/color_encoding_internal.cc

[5] libjxl/libjxl, "libjxl/lib/include/jxl/codestream_header.h" https://github.com/libjxl/libjxl/blob/ff8a9c1c/lib/include/jxl/codestream_header.h#L130-L155

[6] Can I use, "JPEG XL image format", https://caniuse.com/jpegxl

PlayStation 5 本体に HDRフォーマットで録画したプレイ動画を DaVinci Resolve で開くための手順

背景と目的

  • 1つ前の記事で筆者は PS5 本体に録画した HDRのプレイ動画の解析を行った

trev16.hatenablog.com

  • 解析は主に DaVinci Resolve を使って行ったのだが、いくつか事前準備が必要だった
  • その手順をメモとして残すことにした

結論

以下の手順で HDRフォーマットで録画したプレイ動画を DaVinci Resolve で開くことが可能となる。

PS5 側の設定

  • ① 事前に PS5 で利用可能な USBドライブを準備し、PS5背面の USBポートに挿しておく
  • ② 「設定」->「キャプチャーとブロードキャスト」->「ビデオクリップ形式」の画面を開く
  • ③ 「ファイル形式」を「効率を優先 (WebM)」に設定する (図1 参照)
    • 筆者が確認したところ MP4 形式で録画すると SDR でしか録画できなかった
    • なお録画解像度を 3840x2160 にすると自動で「効率を優先 (WebM)」になる
  • ④ PS5 でゲームを起動しコントローラーのクリエイトボタンを押して録画を行う
  • ⑤ PS5 のメディアギャラリーを開き、USBドライブにコピーする (動画1 参照)

図1. ビデオクリップ形式の画面


動画1. PS5 本体で録画したデータを USBドライブにコピーする様子

PC 側の設定

  • ① USBドライブの録画データを PC にコピーする
  • FFmpeg を使って mp4 コンテナに変換する
    • 変換しなくても DaVinci で開けるのだが、音声が消えてしまうため .webm -> .mp4 に変換する
    • 以下に示した FFmpeg パラメータのうち、大事なのは -color_range tv である。これがないとメタデータのミスマッチが発生した
ffmpeg -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc -color_range tv -i INPUT_FILE_NAME.webm -c:v copy -c:a copy -color_primaries bt2020 -color_trc smpte2084 -colorspace bt2020nc -color_range tv OUTPUT_FILE_NAME.mp4
  • ③ 変換した .mp4 ファイルを DaVinci で開く

注意事項

USBドライブから PC に .webm ファイルをコピーする際に、本当に HDR形式で録画できているか確認することをお勧めする。 筆者は MPC-BE という再生プレイヤーで .webm ファイルを開き、「File」-> 「Properties」を選択してメタデータを確認するようにしている。

図2 のように Color primaries と Transfer characteristics が BT.2020 と PQ となっていれば HDRフォーマットで録画できている。

図2. MPC-BE を使って .webm ファイルのメタデータを確認している様子

PS5 の「HDR調整」と「プレイ動画の録画機能」の関係を軽く調べた(FINAL FANTASY 16 を使用)

1. 背景

筆者は FINAL FANTASY 16 (以後 FF16 と略す) をプレイするために PlayStation 5 (以後 PS5 と略す) を購入した。 PS5 は HDR をサポートしたゲーム機であり、HDR に関して以下の特徴がある。

  • HDR調整という機能があり HDR対応ゲームの表示を表示デバイスに最適化できる
  • HDR のゲームプレイ動画を PS5本体に HDRフォーマットで録画できる
  • 録画した動画は YouTubeHDRフォーマットで投稿できる

筆者は個人的な興味から PS5 本体に録画したプレイ動画の解析を行っていたが、録画データを観察しているうちに HDR調整と録画データの関係が気になった。 具体的には 録画データに HDR調整の結果が反映されるのか、PS5 本体に録画したプレイ動画を YouTube にアップした際に、HDR調整の結果によって動画の見た目が変わるのか、といったことが気になった。

そうした背景があり簡単な調査を行うことにした。

2. 目的

  1. PS5の HDR調整結果が PS5本体のプレイ動画の録画データに反映されるか調べる
  2. 上記の結果を元に、録画した FF16の HDRプレイ動画を YouTube にアップロードする場合の注意点があれば記載する

3. 結論

3.1. 結論1

PS5の HDR調整結果は PS5本体のプレイ動画の録画データに反映される。

そのため、例えば複数人のプレイヤーが同じシーンを録画して YouTube にアップした場合には、 各プレイヤーの HDR調整結果によって動画の輝度レンジが異なる結果となる。

確認のために 4種類のパラメータで HDR調整を行い、同一のシーンを録画した結果を動画1 に示す。


動画1. 異なる複数のパラメータで HDR調整を行った場合の比較。動画の後半に輝度分布の分析あり。

3.2. 結論2

YouTube へ FF16 のHDRプレイ動画をアップする際、PS5 の HDR調整結果は殆ど気にする必要はないと考える。 なぜならば YouTube にアップロードした動画を各種 HDR対応デバイスで確認したところ、HDR調整の結果によらず HDR感のある動画として知覚できたからである。

一方で、データレベルでは高輝度のシーンの描画結果には差異があったため (図1参照)、気になるユーザーは録画をする時だけ HDR調整の Highlight側の Adjustment Index (※1) を 15 以上に設定することをオススメする。

※1 Adjustment Index については後述するが、一旦ここで Index とターゲット輝度の関係を図2 に示す。

図1. 異なる HDR調整結果での輝度の比較 図2. HDR調整の Adjustment Index と輝度(推測値)の関係

3.3. 使用機材、ソフトウェア

検証に使用した機材とソフトウェアは以下の通りである。

名称 バージョン
PlayStation 5 (CFI-1200B) 23.01-07.40.00.06-00.00.00.0.1
FINAL FANTASY 16 Version 1.02
Elgato 4K60 S+ (HDMI キャプチャ機材) 不明
Elgato 4K Capture Utility Version 1.7.6

4. 結論に至までの経緯

4.1. PS5 の HDR調整に関する調査

始めに PS5 の HDR調整に関する調査を行った。結果を以下に示す。

4.1.1. HDR調整の概要

HDR調整は PS5 の 「ホーム」->「設定」->「スクリーンとビデオ」にある設定項目である。

取扱説明書には テレビに合わせて明るさを構成することで、HDRを最適化してより美しい映像を体験できます との記載がある。 この「HDRを最適化して」という文言が具体的にどのような処理を意味するのかは不明だが(※2)、上記の文言から PS5 内部で HDR調整の結果に基づきゲーム映像に何らかの処理が適用されることが推測できる。

さて HDR調整の具体的な内容だが、調整は 図3~図5 に示す 3種類のパターンを使って行う。 プレイヤーは各パターンの明るさを変更して使用している表示デバイスに最適なポイントを探す。

図3. HDR調整 (1/3) 図4. HDR調整 (2/3) 図5. HDR調整 (3/3)

パターンの明るさ変更は 32段階 or 16段階で行うことができる。図3 と 図4 の調整は 32段階、図5 は 16段階の調整となっている。

4.1.2. HDR調整の用語整理

さて、突然だが本記事では 図3、図4 の調整を Highlight側の調整、図5 の調整を Shadow側の調整と呼ぶことにする。 理由は名前を付けないと記事が書きづらいからである。なお、これは筆者独自の呼び方であり一般的な呼び方ではないことに注意して頂きたい(※3)。

同様に 32段階 or 16段階の調整点を Adjustment Index と呼ぶことにする。

※2 そこそこ調べたのだが処理内容に言及している公式の文書は見つからなかった
※3 そもそも一般的な呼び方が分からなかったので筆者は独自の呼び方をすることにした、という背景がある

4.1.3. Adjustment Index と対応する輝度の関係の調査

さて、ここまで調べると Adjustment Index を変化させた際のパターンの輝度が気になってくる。 そこで筆者は自宅にある Elgato 4K60 S+ (以後はキャプチャ機材と呼ぶ) を使って調査した。

Adjustment Index を変化させた際の信号の生値をプロットした結果を図6に、それを輝度値に変換した結果を図7 に示す。

図6. 信号生値のプロット結果 図7. 輝度値に変換後のプロット結果

図6、図7 を細かく観察すると、グラフは歪んでおり また最大値も 10000 nits に達しておらず不自然なことが分かる。 筆者はこの原因はキャプチャ機材に問題があると考えた。そこで少々乱暴ではあるが上記のグラフを推測に基づき修正することにした。

修正後の値を以下のテーブルにて赤字で示す。また、グラフをプロットしなおした結果を図8、図9 に示す。

項目 生値(測定値) 生値(修正後の推測値) 輝度値(測定値) 輝度値(修正後の推測値)
Highlight 517 ~ 1006 520 ~ 1023 97 ~ 8536 100 ~ 10000
Shadow 0 ~ 144 0 ~ 152 0 ~ 0.832 0 ~ 1.00
図8. 信号生値のプロット結果 (修正後の推測値) 図9. 輝度値に変換後のプロット結果(修正後の推測値)

なお、図6~図9 は HDR調整時の Adjustment Index と輝度値の対応関係を示しただけである。 ゲームの出力輝度が Adjustment Index の輝度値に制限されるとは限らないので誤解のないようにして頂きたい (※4※5)。

※4 PS5 の説明書に書かれているのは「HDRを最適化してより美しい映像を体験できます」という点のみであり、出力輝度の範囲に関する明確な記述は無い
※5 筆者が確認したところ FF16 のゲーム画面は Adjustment Index で設定した輝度値よりも高い輝度値も出力されていた

4.2. HDR調整と PS5 の録画データの関係

さて、これまでの調査で HDR調整の概要は理解できた。続いて FF16 のゲーム画面がどのように変化するかを確認した。 まず筆者は PS5 本体にプレイ動画を録画した際に HDR調整の結果が適用されるか確認することにした。

なぜ、このような確認をしたかというと、筆者は HDR調整が適用されるのは HDMI出力のみで、内部録画データには適用されないと推測していたからである。 しかし確認したところ、HDR調整の結果は HDMI出力と内部録画データの両方に適用されていた。確認時のゲーム画面の輝度分布の比較を図10 に示す。

図10. HDMI出力結果と PS5 内部録画データの輝度比較

図10 の各ブロックの説明は以下の通り。右上と右下の輝度レンジが一致していることから、HDR調整の結果は内部録画データにも適用されることが分かる。

場所 Highlight側の Adjustment Index 対応する輝度 確認対象
左上 31 約10000 nits HDMI出力
右上 0 約100 nits HDMI出力
右下 0 約100 nits PS5 内部録画データ

4.3. PS5 の録画データの YouTube 投稿結果の目視確認

4.3.1. YouTube 投稿結果の目視確認を行う理由

ここまでの調査で PS5 の録画データに HDR調整の結果が適用されることが分かった。 最後に HDR調整が適用されたデータをそのまま YouTube にアップロードして問題がないか簡単な確認を行った。

なぜこのような確認を行ったかというと、ユーザーの使用している表示デバイスの輝度レンジの差によって以下の問題が生じることを恐れていたからである。

  • ユーザーA は ピーク輝度 400 nits の Display HDR 400 対応モニターを所有していた
    • ユーザーA は PS5 の HDR調整で Highlight側の Adjustment Index を 9 (約 400 nits) に設定した
    • ユーザーA は FF16 の HDRプレイ動画を PS5 内部に録画した
    • ユーザーA は 録画データを YouTube にアップロードして一般公開した
  • ユーザーB は ピーク輝度 1600 nitsiPad Pro を所有していた
    • ユーザーB は ユーザーA が投稿した FF16 のプレイ動画を視聴した
    • ユーザーB は「なんか高輝度が出ていなくてHDR感が少ないな~」という印象を持ってしまった
4.3.2. 確認手順

確認は以下の手順で行った。

  • ① 以下の表に示す通り Highlight側の Adjustment Index を 4種類用意した
Adjustment Index 対応する輝度 用意した理由
0 約100 nits 参考比較用に理論的な最低値を指定(目視評価のターゲットではない)
9 約400 nits 実用的な最低値を指定。Display HDR の最低グレードに合わせた
15 約1000 nits 映像制作市場における基準輝度が 1000 nits であるため指定
25 約4000 nits 個人的にありそうだと考える最大値を指定。Dolby Vision の基準輝度


  • ② それぞれのHDR調整が適用された FF16 の HDRプレイ動画を PS5にて録画した
  • ③ 比較しやすいよう DaVinci Resolve を使って 4つの録画データを結合し YouTube にアップロードした
  • ④ 輝度レンジの異なる 5種類のデバイスYouTube にアップロードした動画を視聴して問題ないか確認した

目視確認に使用したデバイスおよびスペックを以下の表に示す。

機材名 ピーク輝度 確認環境
Pixel 4 XL 約450 nits YouTube App Version 18.25.39
G3223Q 約600 nits Microsoft Edge Version 114.0.1823.67
BRAVIA 65X9500G 約1200 nits YouTube App Version 3.05.003
iPhone 13 Pro 約1200 nits YouTube App Version 18.25.1
iPad Pro 12.9-inch (第5世代) 約1600 nits YouTube App Version 18.25.1

なお、確認に使用した動画は結論欄に貼り付けた動画である。念のため以下に再掲する。


動画1 (再掲). 異なる複数のパラメータで HDR調整を行った場合の比較。動画の後半に輝度分布の分析あり。
4.3.3. 確認結果

さて、各デバイスで視聴した結果であるが、筆者が観察した限りでは Adjustment Index 9 (約400 nits) でも十分に明るさを知覚でき、特に暗いという印象は受けなかった。 もちろん、ごく一部に存在する高輝度領域では白飛びによりディテールが失われることもあったが、動画を一時停止してコマ送りしないと気づかないレベルであった。 そのため、筆者は冒頭の結論で述べた通り YouTube への動画のアップロード時に HDR調整の結果は気にする必要ないと考えている。

なお、この結果は FF16 の HDRプレイ動画の結果であり、他のゲームソフトでも同じ傾向にあるかは不明である。その点は注意して頂きたい。

5. 感想

HDR調整の内容が気になって FF16 のプレイを中断してブログを書いていたが、これでやっと FF16 のプレイを再開できるぜ。

DaVinci Color Transform Language (DCTL) を使った printf デバッグを試した

1. 背景

前回、筆者は以下の記事で DaVinci Color Transform Language (DCTL) を試し、得られた知見を記事にまとめた。

trev16.hatenablog.com

その中で筆者は「コンソール出力が無いので printf デバッグすらできない」という旨を書いた。

すると、記事を読んでくださった有識者の方から、少々トリッキーではあるが、printfデバッグの方法を教わることができた。 また非常にありがたいことに、その方からは DCTL のサンプルコードも頂いた(本当にありがとうございます🙏)。

ただ、サンプルコードの内容は難解であり、筆者は処理内容を理解することができなかった。 そこで、自己の理解を深めるためにスクラッチから printf デバッグ用の DCTL ファイルを作成することに決めた。

2. 目的

printf デバッグ用の DCTL ファイルを作成する。

3. 結論

指定した座標の RGB値を画面表示する DCTL ファイルの作成に成功した (本記事ではこの画面表示が printf デバッグを意味する)。 その様子を 図1 および 動画 1 に示す。

図1. printf デバッグ (という名の数値表示) をしている様子

動画1. printf デバッグ (という名の数値表示) をしている様子

4. やり方

やり方はシンプルである。 図1 を見れば分かるようにデバッグ情報(数値)を画面に描画することで実現している。

どのようにして図1 の描画に至ったのか、順を追って説明する。

4.1. DCTL を使った図形の描画

DCTL では画面出力の RGB データに直接アクセスできるため、任意の図形をプロットすることが可能である。 例えば以下のコードを書くと、画面左上に黄色の矩形を描画できる。

__DEVICE__ float3 transform(int p_Width, int p_Height, int p_X, int p_Y, float p_R, float p_G, float p_B)
{
    float3 out = make_float3(p_R, p_G, p_B);
    float3 rectangle_color = make_float3(1.0, 1.0, 0.0);
    float2 st_pos = make_float2(200, 100);
    float2 ed_pos = make_float2(1200, 300);
    
    if((st_pos.x <= p_X) && (p_X < ed_pos.x)){
        if((st_pos.y <= p_Y) && (p_Y < ed_pos.y)){
            out.x = rectangle_color.x;
            out.y = rectangle_color.y;
            out.z = rectangle_color.z;
        }
    }

    return out;
}

図2. 画面左上に矩形 (黄色) を描画した様子

4.2. 矩形を組み合わせた数値の描画

矩形が書けてしまえば、矩形の組み合わせで任意の数字の描画が可能である。 筆者は下図のように A~H の 8個の矩形を用いて数値と小数点を描画することにした。

図3. 8個の矩形の組み合わせで数値と小数点を表現する様子

4.3. 表示用の数値の取得および描画

DCTL では _tex2D 関数を使う事で任意の座標の RGB 値を float型で取得できる。

取得値は float 型であるため、本来であれば 1.2345E-5 のような指数表記で描画するのが好ましかったのだが、 実装が面倒だったので、今回は固定小数点ライクな表示仕様とした。

その結果、正の数は6桁、負の数は5桁での表示となった。表示の様子を図4 に示す

図4. 色々な数値を描画がしている様子

表現可能な数値の範囲は以下の通りである (0を除く)。

  • 正の数: 0.00001 ~ 999999
  • 負の数: -0.0001 ~ -99999

5. ソースコード

一応、以下に置いときます。例によってコメントを全然書いて無いですが…。

printf デバッグに必要なのは 私のリポジトリ にある以下の2ファイルです。

6. 感想

この DCTLコードの実装は想像よりずっと楽しかった。満足したので元の作業に戻る。