背景
- 筆者は自宅で使っている OLEDモニター (AW3225QF) の表示特性に不満を持っていた(前回の記事で触れた[1])
- HDR Peak 1000 モードでは APL の増加に伴う輝度低下が非常に大きい
- 一方で DisplayHDR True Black モードでは高輝度領域の白飛びが激しい
- 調べ物をしていたところ、Windows ではモニター用の ICC Profile に MHC2タグを追加することで HDR信号の出力を制御できることが分かった
- これにより筆者の不満点をある程度解消できる可能性が出てきた
- ということで実際に試してみた
目的
結論
- MHC2 タグの仕様を理解した
- MHC2 タグを使い Windows が出力する HDR信号を任意の値に変換することに成功した
- 今回は出力信号の gain を変更し HDR信号の輝度低下を実現した
- OLEDモニターの DisplayHDR True Black モードとの組み合わせにより「白飛びの軽減」と「 APL増加にともなう輝度低下の軽減」を実現した
- 作成した MHC Profile を参考データとして以下に添付する *3
ただし、現状では以下の問題があるため実運用には向いていない
確認に使用したソフトウェアのバージョンは以下の通り。
Software | Version |
---|---|
Windows | Windows 11 Pro 23H2 Build 22631.3374 |
Photoshop | 25.6.0 |
Affinity Photo | 2.4.1 |
詳細
筆者が所有している OLEDモニター(AW3225QF)の不満点
冒頭でも述べた通り、筆者は AW3225QF に対して以下の不満点を持っている。
- HDR Peak 1000 モードでは APL*5 の増加に伴い急激な輝度低下が発生する(図1 参照)
- DisplayHDR True Black モードでは高輝度領域の白飛びが激しくディテールが消えてしまう(図2 参照)
図1. 急激な輝度低下が発生している様子XDR Display は比較用の表示。撮影は同一条件で実施 | 図2. 高輝度領域が白飛びする様子XDR Display は比較用の表示。撮影は同一条件で実施 |
輝度低下および白飛びが発生するのは AW3225QF が特殊な表示特性を有しているからである。 以前に筆者が測定したデータを以下に再掲する[2]。
図3. HDR Peak 1000 の測定結果 | 図4. DisplayHDR True Black の測定結果 |
図3 と図4 から以下のことが分かる。
- 図3: HDR Peak 1000 では APL の増加に伴い急激に輝度が低下する
- 図4: DisplayHDR True Black では 300 nits 以降のデータに強めのトーンマッピングが適用され白飛びしやすい
筆者はこの問題への対処方法の 1つとして「DisplayHDR True Black で表示しつつ、入力信号の輝度を半分に低下させる」手法を試したいと考えていた。そうすることで以下の効果が得られると考えたからである。
ということで、後述の MHC2 タグを使って輝度を下げることを試した。
ICC Profile の MHC2 タグについて
Windows 10 (20H1) 以降、Windows にはモニターのキャリブレーションの仕組みが導入されている[3]。 図5 の 2b, 3b にある通り Windows の出力信号に対して 3x3 の Matrix と 1DLUT を適用することができる。
3x3 の Matrix と 1DLUT はモニターの ICC Profile に MHC2 タグを埋め込むことで有効化できる。
MHC2 タグの詳細は以下の通り[3]。なお、MHC2 タグは Windows 独自のタグであり ICC の仕様書 には存在しないので注意して頂きたい。
"MHC2" private tag definition
Byte Position | Field Length (bytes) | Content | Data type |
---|---|---|---|
0 to 3 | 4 | 'MHC2' (4D484332h) Type Signature | MHC2Type |
4 to 7 | 4 | Offset to beginning of tag data element | uint32Number |
8 to 13 | 4 | Size of tag data element | uint32Number |
MHC2Type structure definition
Byte Position | Field Length (bytes) | Content | Data type |
---|---|---|---|
0 to 3 | 4 | 'MHC2' (4D484332h) Type Signature | |
4 to 7 | 4 | Reserved, set to 0 | |
8 to 11 | 4 | Number of 1DLUT entries (4096 or less) ※aOPTIONAL: 0 = Identity Transform | uint32Number |
12 to 15 | 4 | ST.2086 min luminance in nits | S15Fixed16Number |
16 to 19 | 4 | ST.2086 peak luminance in nits | S15Fixed16Number |
20 to 23 | 4 | Offset in bytes to matrix ※bOPTIONAL: 0 = Identity Transform | uint32Number |
24 to 27 | 4 | Offset in bytes to red 1DLUT ※b | uint32Number |
28 to 31 | 4 | Offset in bytes to green 1DLUT ※b | uint32Number |
32 to 35 | 4 | Offset in bytes to blue 1DLUT ※b | uint32Number |
※a OS はハードウェアがサポートするエントリの数にデータを補間する ※b オフセットは、ファイルの始まりからではなく、MHC2 タグの開始位置からのオフセットである
Matrix definition
Byte Position | Field Length (bytes) | Content | Data type |
---|---|---|---|
0 to 23 | 24 | 3x4 XYZ to XYZ adjustment matrix stored in row major order, column 4 is ignored ※c ※d | s15Fixed16Number |
※c Matrix は 3x3 なのだが MHC2 タグのデータ上は 3x4 として定義する必要がある(最後の1要素は 0 で良い) ※d 例えば何も変換を行わない単位行列を宣言する場合は [0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000] となる(S15Fixed16Number にて記述)
1DLUT definition
Byte Position | Field Length (bytes) | Content | Data type |
---|---|---|---|
0 to 3 | 4 | 'sf32' (73663332h) Type Signature | |
4 to 7 | 4 | Reserved, set to 0 | |
8 to end | Variable (0 to 16384) | Calibration LUT values normalized to [0.0, 1.0] ※e | s15Fixed16Number |
※e この 1DLUT は Non-Linear 空間に対して適用される。Linear 空間ではないので注意が必要である
MHC2タグ用のデータ作成 (1DLUT)
タグの仕様を理解したところで筆者は MHC2タグ用のデータ作成を行った。今回は輝度低下が目的であったため図5 (3b) の 1DLUT の値のみ変えることにして、図5 (2b) の Matrix にはデータ変換を行わない単位行列を設定することにした。
図5 (3a) を見ると分かる通り、1DLUT が適用される空間は Linear 空間ではなく Non-Linear 空間である。具体的には SMPTE ST 2084 の EOTF^-1 が適用された後の空間である。 そのため 1DLUT は以下の計算式で作成した。
-
- : 図5 (3a) の出力信号
- : 1DLUT 適用後の信号
- : SMPTE ST 2084 EOTF
- : 輝度の低下率。今回は 0.5 とする
少し分かりづらいかもしれないので、3ステップに分けて処理内容を書いておく。
- ① に対して SMPTE ST 2084 EOTF を適用して Linear化
- ② Linear空間でゲイン を適用
- ③ SMPTE ST 2084 EOTF^-1 を適用して Non-Linear化
実際に 1DLUT を計算した様子を以下に示す。
from colour.models import eotf_ST2084, eotf_inverse_ST2084 import numpy as np import matplotlib.pylab as plt num_of_sample = 256 gain = 0.5 step1 = np.linspace(0, 1, num_of_sample) step2 = eotf_ST2084(step1) * gain step3 = eotf_inverse_ST2084(step2) plt.plot(step1, step3) plt.grid(True) # Enable grid plt.xlim(0.0, 1.0) # Set x-axis range plt.ylim(0.0, 1.0) # Set y-axis range plt.show()
MHC2タグを埋め込んだ ICC Profile の作成
データができたので、あとは仕様通りに ICC Profile にデータを埋め込めば良い。 筆者は過去に ICC Profile を作った経験があったので、今回もその環境を流用して MHC2タグの埋め込みを行った。
なお、SMPTE ST 2086 のメタデータは以下の値を設定した*6。
Item | Value |
---|---|
Peak luminance (nits) | 10000 |
Max full frame luminance (nits) | 10000 |
Min luminance (nits) | 0.001 |
RGB color primaries (xy coordinates) | BT.2020 の値 |
White point (xy coordinates) | いつもの D50 |
MHC2タグを埋め込んだ ICC Profile の確認
作成した MHC2タグは Microsoft独自のタグであり、ICC が提供する公式のツールではデータの正当性を確認できない。 やむを得ず筆者はバイナリエディタを使って目視確認することにした。
1DLUT のエントリ数を 8、輝度低下のゲインを 0.5 とした際の ICC Profile についてバイナリエディタで確認を行った様子を以下に示す*7。
図番号と詳細 | 図 |
---|---|
図7①MHC2のデータ開始アドレスは 0x0260 | |
図8②1DLUTのエントリ数は 8③Matrix の開始位置は 0x0260+0x0024=0x0284④1DLUT (R) の開始位置は 0x0260+0x0054=0x02B4⑤1DLUT (G) の開始位置は 0x0260+0x007C=0x02DC⑥1DLUT (B) の開始位置は 0x0260+0x00A4=0x0304 | |
図9⑦3x4 Matrix データ (色変換を行わないスルー設定) | |
図10⑧1DLUTデータ。それっぽい単調増加データとなっている |
図7~図10 の確認を経て、筆者は正しく ICC Profile が作成できたと判断した。
Windows 上で ICC Profile の適用
Color Management のダイアログボックスを表示後、「Add...」ボタンから作成したプロファイルを登録し、その後に「Set as Default Profile」で Default のプロファイルに設定すれば良い。gain=0.5 のプロファイルを設定している様子を図11 に示す。
実コンテンツを使った効果確認
Netflix が評価用に無償公開している Sol Levante を使って確認した。
主観評価で大変申し訳ないのだが確認結果は以下の通りである。
- 筆者は MHC2 タグで輝度を半分に落とすことで以下の問題を改善できたと知覚した
- APL の増加に伴う急激な輝度低下
- 高輝度領域の白飛び
- よって目的を達成できたと判断した
なお、HDR動画の再生プレイヤーには MPC-BE を使用した。また MPC-BE の Video renderer には MPC Video Renderer を使用した。
現状の問題点
目的を達成できた一方で、冒頭でも述べた通り現状では少なくとも 2点の問題がある。
- Windows のログイン直後は MHC2 タグの内容が反映されない
- ログイン後に図11 のダイアログを表示してプロファイルの再設定が必要
- Photoshop 2024 にて SDR 画像の色ズレが発生する
- Photoshop と Affinity Photo 2 の比較を図12、図13 に示す
- なぜこのような結果になるかは不明(筆者の作成したプロファイルに問題がある可能性もある)
図12. Photoshop で画像を開いた様子 | 図13. Affinity Photo 2 で画像を開いた様子 |
こういった状況のため、一般的なユーザーが使うのは少し難しいと考えている。 一方で自分のような人間が趣味で使う分には問題ないと考える。
感想
MHC2タグのデータを色々と変えて信号の変化を観察するのは面白かった。 しかし、一般的なユーザーが使いこなすのは相当に困難だと感じている。
今回の記事では述べなかったが Windows OS を経由した HDRの表示は「OS側の色変換」「アプリの色変換」「モニターの色変換」が複雑に絡み合うため挙動を理解するのが大変難しい。とても他の人にはオススメできない。
Windows がこんな状況なので、やはり現時点では iPhone, iPad, MacBook Pro が自分の中でのオススメ製品になってしまう。 うーん、何とかこの複雑な状況を整理してあらゆるユーザーが安心して HDR表示できる環境を整えたい…。
参考資料
[1] toruのブログ, "AW3225QF を使い FINAL FANTASY VII REBIRTH をプレイする際に生じる HDR表示のトレードオフについて", https://trev16.hatenablog.com/entry/2024/03/17/222252 [2] toruのブログ, "DaVinci Resolve と Argyll CMS を使ってゲーミングモニター (AW3225QF) の特性を測ってみた", https://trev16.hatenablog.com/entry/2024/02/28/215831 [3] Microsoft Learn, "Windows hardware display color calibration pipeline", https://learn.microsoft.com/en-us/windows/win32/wcs/display-calibration-mhc
*1:後ほど軽く述べるがモニターのキャリブレーションを行うための仕組みである
*2:次の記事でアプリケーションのトーンマッピングの話と絡めて詳しく解説するかも
*3:筆者は MHC2_10000-10000-nits_gain-0.50.icm を日常的に使っている
*4:ちなみに Affinity Photo 2 は問題なかった
*5:APL は Average Picture Level の略語
*6:ピーク輝度を 10000 nits としたのは意図しないトーンマッピングの適用を避けるためである。詳細は次の記事で述べる…かもしれない
*7:ICC Profile は Big Endian である。そのため普段は Little Endian で暮らしている人は注意が必要である