toruのブログ

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

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