toruのブログ

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

Ultra HDR の画像データを作ってみた

背景

  • Android 14 から Ultra HDR と呼ばれる静止画フォーマットがサポートされている
  • その名前の通り HDR をサポートした静止画フォーマットであり、筆者は以前から試してみたいと考えていた
  • そこで実際に Ultra HDR の画像を作ってみることにした

目的

  • Ultra HDR の仕様について簡単に調べる
  • Ultra HDR の画像データを作成する

結論

Ultra HDR の仕様について

筆者は Ultra HDR の仕様について以下の通りに理解した。

  • 画像フォーマットの JPEG を拡張し HDR コンテンツをサポートしたものである
  • 後方互換性を有しており HDR をサポートしないデバイスでは SDRの JPEG画像として扱われる *1
  • SDR/HDR の双方をサポートするために Gain Map が使われている
    • Gain Map の扱いは筆者が以前に調査を行った Adobe/Apple の Gain Map HDR と同じである *2

Gain Map HDR *3 については筆者の過去記事を参照。

trev16.hatenablog.com

Ultra HDR の画像生成について

libultrahdrultrahdr_appを使うことで Ultra HDR の画像生成に成功した。 作成した画像を以下に示す。HDR表示に対応しているデバイスであれば HDR として表示される。その一方で HDR非対応のデバイスであれば SDR として表示される。

img1 img2
図1. テストパターン画像 (Rec.2100-PQ) 図2. テストパターン画像 (Rec.2100-HLG)


img3 img4
図3. 自然画1 (Rec.2100-PQ) 図4. 自然画2 (Rec.2100-PQ)

なお、Windows 上で Ultra HDR の画像を確認する際は、SDR content brightness の設定を 31 にすることを推奨する。 SDR content brightness と静止画の HDR表示の関係については筆者の過去記事を参照。

trev16.hatenablog.com

詳細

Ultra HDR の仕様について

Ultra HDR Image Format v1.0 参照。

Ultra HDR の画像生成について

Ultra HDR の画像は libultrahdr のビルド時に生成されるultrahdr_appを使うことで生成できる。

筆者が行った手順は以下の通り。順番に説明する。

  1. libultrahdrのビルド
  2. ultrahdr_appの仕様を確認
  3. ultrahdr_appに入力する各種データの作成
  4. ultrahdr_appの実行


libultrahdr のビルド

README.md に従ってビルドした。特記事項なし。


ultrahdr_app の仕様を確認

ultrahdr_appを実行すると以下の usage が表示された。encode scenario というのが 0~4 まであるが、 これは README.md の Encoding api outline に詳細が書かれている。 今回は encode scenario 4 に従って Ultra HDR画像を生成することにした。なぜならば筆者は gain map を自分で生成しつつ、メタデータもマニュアルで指定したかったからである。

## ultra hdr demo application.
Usage : ultrahdr_app 
    -m    mode of operation. [0:encode, 1:decode] 

## encoder options : 
    -p    raw hdr intent input resource (10-bit), required for encoding scenarios 0, 1, 2, 3. 
    -y    raw sdr intent input resource (8-bit), required for encoding scenarios 1, 2. 
    -a    raw hdr intent color format, optional. [0:p010, 5:rgba1010102 (default)] 
    -b    raw sdr intent color format, optional. [1:yuv420, 3:rgba8888 (default)] 
    -i    compressed sdr intent input resource (jpeg), required for encoding scenarios 2, 3, 4. 
    -g    compressed gainmap input resource (jpeg), required for encoding scenario 4. 
    -w    input file width, required for encoding scenarios 0, 1, 2, 3. 
    -h    input file height, required for encoding scenarios 0, 1, 2, 3. 
    -C    hdr intent color gamut, optional. [0:bt709, 1:p3 (default), 2:bt2100] 
    -c    sdr intent color gamut, optional. [0:bt709 (default), 1:p3, 2:bt2100] 
    -t    hdr intent color transfer, optional. [0:linear, 1:hlg (default), 2:pq] 
    -q    quality factor to be used while encoding sdr intent, optional. [0-100], 95 : default.
    -e    compute psnr, optional. [0:no (default), 1:yes] 
    -R    color range of hdr intent, optional. [0:narrow-range (default), 1:full-range]. 
    -s    gainmap image downsample factor, optional. [integer values in range [1 - 128] (4 : default)]. 
    -Q    quality factor to be used while encoding gain map image, optional. [0-100], 85 : default. 
    -G    gamma correction to be applied on the gainmap image, optional. [any positive real number (1.0 : default)].
    -M    select multi channel gain map, optional. [0:disable (default), 1:enable]. 
    -x    binary input resource containing exif data to insert, optional. 

## decoder options :
   (省略)

## common options :
    -z    output filename, optional.
          in encoding mode, default output filename 'out.jpeg'.
          in decoding mode, default output filename 'outrgb.raw'.
    -f    gainmap metadata config file.
          in encoding mode, resource from which gainmap metadata is read, required for encoding scenario 4.

## examples of usage :

## encode scenario 0 :
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -a 0
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -w 1920 -h 1080 -q 97 -a 5
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -C 1 -t 2 -a 0
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -w 1920 -h 1080 -q 97 -C 1 -t 2 -a 5

## encode scenario 1 :
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 -h 1080 -q 97 -a 0 -b 1
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -y cosmat_1920x1080_rgba8888.raw -w 1920 -h 1080 -q 97 -a 5 -b 3
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 -h 1080 -q 97 -C 2 -c 1 -t 1 -a 0 -b 1
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -y cosmat_1920x1080_rgba8888.raw -w 1920 -h 1080 -q 97 -C 2 -c 1 -t 1 -a 5 -b 3
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 -h 1080 -q 97 -C 2 -c 1 -t 1 -e 1 -a 0 -b 1

## encode scenario 2 :
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -O 3 -e 1 -a 0 -b 1
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -y cosmat_1920x1080_420.yuv -i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -O 3 -e 1 -a 5 -b 1

## encode scenario 3 :
    ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 1 -O 5 -e 1 -a 0
    ultrahdr_app -m 0 -p cosmat_1920x1080_rgba1010102.raw -i cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 1 -O 5 -e 1 -a 5

## encode scenario 4 :
    ultrahdr_app -m 0 -i cosmat_1920x1080_420_8bit.jpg -g cosmat_1920x1080_420_8bit.jpg -f metadata.cfg

## encode at high quality :
    ultrahdr_app -m 0 -p hdr_intent.raw -y sdr_intent.raw -w 640 -h 480 -c <select> -C <select> -t <select> -s 1 -M 1 -Q 98 -q 98

## decode api :
    (省略)


ultrahdr_app に入力する各種データの作成

encoding scenario 4 に必要なデータは以下の 3種類である。どのように生成したのか順に説明する。

  • ① 8-bit JPEG 形式の gain map画像
    • なお gain map を作るためには SDR画像とHDR画像が必要となる
  • ② 8-bit の JPEG 形式の SDR画像
  • ③ gain map 用のメタデータファイル (.cfg)

まず ① の gain map 画像について。これを作るために筆者は SDR と HDR の画像をそれぞれ用意した。 例を以下に示す。これは冒頭の図1 の Ultra HDR の元となった 16-bit PNG 画像である。

図5. SDR画像 (Rec.2020-sRGB) 図6. HDR画像 (Rec.2100-PQ)

図5、図6 のキャプションからわかるように、今回は SDR/HDR の双方で同じ色域 (Rec.2020) とした。 これは後の Gain Map 計算の際に色域が異なるのが好ましくないからである。詳細は Gain Map HDR の過去記事の 5.3.2. を参照。

筆者は図5、図6 の画像データから gain map 画像を作成した。計算は仕様書どおりに行ったので細かな内容は省略する。 作成した gain map画像を図7 に示す。今回準備した SDR 画像は HDR画像から生成したものではないため*4、一部で変な gain map となっているが理論上は問題ない(はず)。

図7. 作成した gain map画像

一応、計算に使用したコードへのリンクを以下に貼り付けておく。

github.com

次に ② の 8-bit JPEG 形式の SDR画像について。これは 図5 の画像 (16-bit PNG) を Python の PIL を使って変換して作成した。

最後に ③ の gain map 用のメタデータファイルについて。GitHubサンプルの .cfg ファイル があったので、これを加工して使用した。

--maxContentBoost 49.076  # 0~1 に正規化された gain map を元に戻すための係数
--minContentBoost 0.0079154  # 0~1 に正規化された gain map を元に戻すための係数
--gamma 1.0
--offsetSdr 0.0078125  # gain map 計算時の 0割を防ぐための係数
--offsetHdr 0.0078125  # gain map 計算時の 0割を防ぐための係数
--hdrCapacityMin 1.0  # weight factor W を計算するためのパラメータ
--hdrCapacityMax 2.3004  # weight factor W を計算するためのパラメータ

なお筆者は--hdrCapacityMin0.0に設定したかったのだが、ultrahdr_app側でエラーになってしまい設定できなかった *5


ultrahdr_app の実行

仕上げとして以下のコマンドライン引数を使用して Ultra HDR 画像を生成した。

ultrahdr_app -m 0 -i ./src_rec2020_srgb_8bit.jpeg -g ./gain_map_src_rec2100-pq-src_rec2020_srgb.jpeg -q 100 -Q 100 -C 2 -c 2 -t 2 -R 1 -f ./metadata_src_rec2100-pq-src_rec2020_srgb.cfg -z ./rec2100-pq_scenario_4.jpeg

感想

実際に画像ファイルを作ってみて、ベースが JPEG なのでファイルサイズが大きくなる傾向にあるなと思った。 なぜ Google陣営は JPEG XL の使用を拒否したのだろうか…。

*1:厳密に言うと Base Rendition を HDR にした場合は後方互換性は担保されないが、話がややこしくなるので本記事では特に言及しない

*2:使われる用語が微妙に異なるので、そこは注意が必要かも…

*3:2023年の WWDC では Gain Map HDR だったが 2024年の WWDC では Adaptive HDR と呼ばれていたため、今後は Adaptive HDR と呼ぶ方が良いかもしれない

*4:一般的には SDR画像は HDR画像にトーンマッピングを適用して作ると思われるが、今回はテストパターンであったためトーンマッピングは適用せずに SDRは独立して作成した

*5:バグの可能性もあるかと考えている