背景
- Android 14 から Ultra HDR と呼ばれる静止画フォーマットがサポートされている
- その名前の通り HDR をサポートした静止画フォーマットであり、筆者は以前から試してみたいと考えていた
- そこで実際に Ultra HDR の画像を作ってみることにした
目的
結論
Ultra HDR の仕様について
筆者は Ultra HDR の仕様について以下の通りに理解した。
- 画像フォーマットの JPEG を拡張し HDR コンテンツをサポートしたものである
- 後方互換性を有しており HDR をサポートしないデバイスでは SDRの JPEG画像として扱われる *1
- SDR/HDR の双方をサポートするために Gain Map が使われている
Gain Map HDR *3 については筆者の過去記事を参照。
Ultra HDR の画像生成について
libultrahdr のultrahdr_app
を使うことで Ultra HDR の画像生成に成功した。
作成した画像を以下に示す。HDR表示に対応しているデバイスであれば HDR として表示される。その一方で HDR非対応のデバイスであれば SDR として表示される。
図1. テストパターン画像 (Rec.2100-PQ) | 図2. テストパターン画像 (Rec.2100-HLG) |
図3. 自然画1 (Rec.2100-PQ) | 図4. 自然画2 (Rec.2100-PQ) |
なお、Windows 上で Ultra HDR の画像を確認する際は、SDR content brightness の設定を 31 にすることを推奨する。 SDR content brightness と静止画の HDR表示の関係については筆者の過去記事を参照。
詳細
Ultra HDR の仕様について
Ultra HDR Image Format v1.0 参照。
Ultra HDR の画像生成について
Ultra HDR の画像は libultrahdr のビルド時に生成されるultrahdr_app
を使うことで生成できる。
筆者が行った手順は以下の通り。順番に説明する。
libultrahdr
のビルドultrahdr_app
の仕様を確認ultrahdr_app
に入力する各種データの作成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 となっているが理論上は問題ない(はず)。
一応、計算に使用したコードへのリンクを以下に貼り付けておく。
次に ② の 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 を計算するためのパラメータ
なお筆者は--hdrCapacityMin
を0.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:バグの可能性もあるかと考えている