toruのブログ

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

HDR対応の HEIC画像を作り iOS/macOS で表示してみたが様子が変だった

1. 背景

  • 筆者は 7年ぶりくらいに開発環境の Dockerfile を整理していた
  • その中で試しに libheif をビルドしてみたところ、割と簡単に HDRに対応した HEIC画像を作成できそうであった *1
    • 筆者は以前から iOS の動作確認用に HDR対応の HEIC画像を作りたいと考えていた
  • そこで作成した HEIC画像を iOS/macOS で表示し、想定通りに表示されるか確認してみた

2. 目的

  • libheif を利用して HDRに対応した HEIC画像を作る
  • 作成した HDR画像を iOS/macOS で表示して特性を確認する

3. 結論

  • ① libheif のビルド時に生成されるheif-encを使い HDRメタデータを埋め込んだ HEIC画像の生成に成功した
    • heif-encの使用例を以下に示す(Rec.2100-PQ 方式の .heic ファイルを作成)
heif-enc --verbose --quality 100 --bit-depth 10 -p chroma=444 --colour_primaries 9 --transfer_characteristic 16 --matrix_coefficients 0 --full_range_flag 1 ./src_png/Rec2100-PQ.png -o ./dst_heif/Rec2100-PQ_cicp_9-16-0_RGB444_10bit.heic


  • iOS/macOS で画像を表示したところ、なぜか異様に低い輝度で表示された
    • 測定結果を図1 に示す *2 *3
    • 原因は不明(きちんと理屈を理解するには AVIF など他の HDRフォーマットも含めた解析が必要だと考える)

図1. iOS (iPhone 15) と macOS (MacBook Pro) で HEIC画像を表示した様子

  • ③ 参考までに筆者が今回の検証用に作成した .heic ファイル一式へのリンクを以下に載せておく

drive.google.com

4. 詳細

4.1. libheif のheic-encを使った HEIC画像の生成

libheif をビルドすると生成されるheif-encを使うと HDR対応の HEIC画像を簡単に生成できる[2]。 以下で手順を説明する。


4.1.1. libheif のビルド

基本的には GitHubREADME.md に従ってビルドすれば良い。筆者はリンク先の Dockerfile の内容でビルドした。


4.1.2. heif-encのオプション確認

heif-enc --help および heif-enc --param を実行すると以下の内容が表示された。次の 3パラメータを適切に設定することでHDR表示用の情報を埋め込めそうである。

  • --matrix_coefficients
  • --colour_primaries
  • --transfer_characteristic
$ heif-enc --help
heif-enc  libheif version: 1.18.2
----------------------------------------
Usage: heif-enc [options] image.jpeg ...

(中略)

Options:
  -h, --help        show help
  -v, --version     show version
  -q, --quality     set output quality (0-100) for lossy compression
  -L, --lossless    generate lossless output (-q has no effect). Image will be encoded as RGB (matrix_coefficients=0).
  -t, --thumb #     generate thumbnail with maximum size # (default: off)
      --no-alpha    do not save alpha channel
      --no-thumb-alpha  do not save alpha channel in thumbnail image
  -o, --output          output filename (optional)
      --verbose         enable logging output (more will increase logging level)
  -P, --params          show all encoder parameters and exit, input file not required or used.
  -b, --bit-depth #     bit-depth of generated HEIF/AVIF file when using 16-bit PNG input (default: 10 bit)
  -p                    set encoder parameter (NAME=VALUE)
  -A, --avif            encode as AVIF (not needed if output filename with .avif suffix is provided)
      --vvc             encode as VVC (experimental)
      --jpeg            encode as JPEG
      --jpeg2000        encode as JPEG 2000 (experimental)
      --htj2k           encode as High Throughput JPEG 2000 (experimental)
  -U, --uncompressed    encode as uncompressed image (according to ISO 23001-17) (EXPERIMENTAL)
      --list-encoders         list all available encoders for all compression formats
  -e, --encoder ID            select encoder to use (the IDs can be listed with --list-encoders)
      --plugin-directory DIR  load all codec plugins in the directory
  -E, --even-size   [deprecated] crop images to even width and height (odd sizes are not decoded correctly by some software)       
  --matrix_coefficients     nclx profile: color conversion matrix coefficients, default=6 (see h.273)
  --colour_primaries        nclx profile: color primaries (see h.273)
  --transfer_characteristic nclx profile: transfer characteristics (see h.273)
  --full_range_flag         nclx profile: full range flag, default: 1
  --enable-two-colr-boxes   will write both an ICC and an nclx color profile if both are present
  --premultiplied-alpha     input image has premultiplied alpha
  --enable-metadata-compression   enable XMP metadata compression (experimental)
  -C,--chroma-downsampling ALGO   force chroma downsampling algorithm (nn = nearest-neighbor / average / sharp-yuv)
                                  (sharp-yuv makes edges look sharper when using YUV420 with bilinear chroma upsampling)
  --benchmark               measure encoding time, PSNR, and output file size
  --pitm-description TEXT   (experimental) set user description for primary image


$ heif-enc --param
Parameters for encoder `x265 HEVC encoder (3.5+1-f0c1022b6)`:
  quality, default=50, [0;100]
  lossless, default=false
  preset, default=slow, { ultrafast,superfast,veryfast,faster,fast,medium,slow,slower,veryslow,placebo }
  tune, default=ssim, { psnr,ssim,grain,fastdecode }
  tu-intra-depth, default=2, [1;4]
  complexity, [0;100]
  chroma, default=420, { 420,422,444 }


4.1.3. heif-enc で指定する HDR表示用の情報についての補足

heif-encでは--transfer_characteristicなどを使って HDR表示用の色情報を指定する。 この情報はヘルプでは nclx profile と書かれている。nclx について少しだけ補足説明をする。

nclx とは ISO Base Media File Format の 'colr' Box のcolour_typeを示している。 ICC Profile を使わず代わりに 4 つの数値情報を使って色空間を表現する際に使用する。 なお、その数値情報は ITU-T H.273 にて定義されている CICP と同じである[3]。


4.1.4. heif-enc を使った変換の実施

筆者は以下のコマンドライン引数を使って Rec.2100-PQ 形式の HEIC画像を生成した。

heif-enc --verbose --quality 100 --bit-depth 10 -p chroma=444 --colour_primaries 9 --transfer_characteristic 16 --matrix_coefficients 0 --full_range_flag 1 ./src_png/Rec2100-PQ.png -o ./dst_heif/Rec2100-PQ_cicp_9-16-0_RGB444_10bit.heic


heif-enc の使用に関する注意事項を以下にまとめておく。

  • --matrix_coefficients 0 を指定する場合は -p chroma=444 の指定も合わせて必要である
    • ロスレス圧縮のために RGB 4:4:4 とするには--matrix_coefficients 0を指定する必要があるが、デフォルト設定の chroma subsampling は 4:2:0 であるため注意が必要である
    • 筆者は -p chroma=444 の指定を忘れると表示が破綻することを確認した
  • --bit-depth 12は使わないほうが良い
    • 筆者は興味本位で bit depth を 12-bit にしてみたのだが、chroma subsampling が YCbCr 4:2:0 でなければビューアーの表示が破綻することが分かった
    • そのため強い動機がなければ 12-bit の使用は控えたほうが良いと考える


4.1.5. 作成した HEIC画像の Code Value の確認

念のために作成した HEIC画像の Code Value が想定通りか DaVinci Resolve 19 を使って確認した。 DaVinci Resolve の Color Page を使用して Code Value を確認している様子を図2 に示す。

図2. DaVinci Resolve を使って作成した HEIC画像の Code Value を確認している様子

4.2. 生成した HEIC画像の表示

4.2.1. 事前準備

今回、HEIC画像の表示を行うデバイスとして以下の 2台を用意した。

再現実験を行えるように筆者が行った事前準備の内容を以下に示す。

まず、MacBook Pro は事前準備として reference mode を有効にした[4] *4MacBook Pro の準備はこれだけである。

一方で iPhone は残念ながら reference mode が存在しなかったので、以下の手順で事前に輝度調整を行った。

  1. 部屋の遮光カーテンを閉めて外光を無くす
  2. デスクライトを弱めの明るさで点灯する(部屋が真っ暗だと iPhone は 1000 nits を出力しなくなるため)*5
  3. iPhone にて Settings -> Display & Brightness -> True Tone を Off に変更
  4. iPhone にて Settings -> Accessibility -> Display & Text Size -> Auto-Brightness を Off に変更
  5. iPhone にて Files app を使い輝度測定用のパッチ動画の 768 / 1023 CV (990 nits) を表示
  6. Colorimeter での測定値が約 1000 nits となるように Settings -> Display & Brightness -> Brightness の値を調整

ここで、手順5 にて静止画ではなく動画を使って輝度調整を行った理由を説明しておく。 理由は Appleディスプレイの調整フロー としてテストパターン動画の利用を推奨していたからである[5]。 筆者はそれを真似した。なお、iOS には Quick Time app が存在しないため代替として Files app を使用した。

最後に各種デバイスのソフトウェアバージョン情報を以下に記載しておく。


4.2.2. 測定

測定は以下の 3種類のアプリケーションに対して行った。

名称 選定理由
Photos iOS / macOS での一般的な静止画表示アプリケーションであるため
Files (iOS) / QuickTime Player (macOS) 静止画と動画とで特性が異ならないか確認する用① *6
YouTube 静止画と動画とで特性が異ならないか確認する用②

Photos app は HEIC画像を、Files/QuickTime Player/YouTube app では HEIC画像を HDR10 動画に変換したものをそれぞれ表示した。

測定用のデバイスには Display Pro HL を、測定用のソフトウェアには Argyll CMSspotreadを使用した。spotreadの使い方については筆者の過去記事を参照して頂きたい。

trev16.hatenablog.com

測定結果を図3、図4 に示す。

図3. iPhone での測定結果 図4. MacBook Pro での測定結果

測定結果から以下のことが分かった。

  • Photos で HEIC画像を表示した場合、他のアプリケーションでの動画表示と比較して明らかに輝度が低くなっている
  • HEIC画像は HDR画像として認識されているようである (1000 nits にてクリッピングが発生しているため)
  • ただし、なぜ輝度が低くなるかは不明
    • 考察していて思ったが JPEG XL や AVIF など、他の静止画HDRフォーマットでも確認が必要だと考える(HEIC特有の問題か切り分けるため)

5. 感想

Windows に続き macOS/iOS での HDR表示の調査を行っているが、色々と怖くなってきた。 私が HDR画像のレタッチに使っていた LightroomHDR表示は本当に正しい表示だったのだろうか…。

6. 参考資料

[1] Wikipedia, "High Efficiency Image File Format", https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format
[2] GitHub, "strukturag/libheif", https://github.com/strukturag/libheif
[3] Wikipedia, "Coding-independent code points", https://en.wikipedia.org/wiki/Coding-independent_code_points
[4] Apple, "Use reference modes with your Apple display", https://support.apple.com/en-euro/108321
[5] Apple, "Measure the calibration of your MacBook Pro with Liquid Retina XDR display, Apple Studio Display, or Apple Pro Display XDR", https://support.apple.com/en-us/105101

*1: HEIC (High Efficiency Image Coding) は HEIF (High Efficiency Image File Format) を使用し、H.265 (HEVC) で画像データを圧縮したものを指す[1]

*2:iPhone 15 は事前に Files App で評価用の ProRes 動画を再生し、最大輝度が 1000 nits となるように Brightness を調整した

*3:MacBook Pro は事前に Displays にて "HDR Video (P3-ST 2084)" プリセットを適用した

*4:具体的には Displays の Preset に "HDR Video (P3-ST 2084)" を設定した

*5:筆者はデスクライト Z-209PROB を1/7 で点灯した

*6:実際、Windows では静止画と動画とで特性が異なる、なんてことが合ったんですよ…