📷

HDR の AVIF を作る

2021/03/20に公開

はじめに

この記事は "AVIF 入りの ImageMagick をビルドする" の続きの記事です。

前回記事では AVIF ファイルの作成のために ImageMagick のビルドをしてみたわけですが、 ImageMagick の AVIF 対応は限定的で HDR 出力はできない、という結論になりました。

ということで HDR の AVIF を作成する方法探しをしました。

AVIF の HDR 関連についてはこちらの記事も大変参考になりますので是非ご一読ください。

AVIF とは

前回記事で書き忘れてしまっていたので改めて。

AVIF は "HEIF" という ビデオコーデックの圧縮技術を静止画用として転用したフォーマット の一種です。 HEIF は大ざっぱには 1 フレーム映像のみの MP4 ファイル と大体同じで、 (対応していれば) ハードウェアデコーダーによる高速化が期待できるのが大きなメリットです。 AVIF はコンテナに HEIF 、コーデックに AV1 を用いたものです。
ちなみに iPhone などで対応している HEIC はコーデックに HEVC (H.265) を用いた HEIF です。

AV1 は HDR に対応しているフォーマットなので、それと同じ形式である AVIF も当然 HDR 対応されており、 Web 用の HDR 静止画フォーマットとして標準化されるのに最も近いものではと思います。現時点で Windows 用の Chrome では HDR 表示を含めて AVIF に対応していることを確認しています。

HDR 対応している AVIF ツール

HDR 対応の条件としては

  • 10bit カラー以上に対応している
  • 色空間のメタデーターが設定できる (BT.2100 PQ が望ましい)

を満たしている必要があります。 ImageMagick では AVIF のオプション指定がなかったので設定ができませんでした。

これらの条件を満たすツールとして

の 2 つがあります。
どちらも 10/12bit, YUV420/422/444, 色空間指定のサポートがあります。

どちらかというと avifenc の方がデコーダー (avifdec) とセットで使えるのでよいかと思います。

cavif は 私がテストした時点のもの では --matrix-coeffcients に bt2020 が指定できませんでした。致命的という程ではないですがあまり望ましくはないかと思います。

ソースとなる PNG を用意する

avifenc, cavif ではどちらもソースとして PNG を要求しています。といってもどのような PNG でもよいわけではありません。

一般的にこの手のエンコーダーは色空間変換までやってくれるわけではなく、 cavif/avifenc も HDR のメタデーターの埋め込みは行ってくれますが、ソースとする映像は 目的の色空間に準拠したもの でなければいけません。一般的には PNG は sRGB 色空間なので大抵のツールでは sRGB にして保存されます。 PNG の仕様的には ICC プロファイルを埋め込む事で様々な色空間に対応することもできますが、今回は BT.2100 PQ で出したいので BT.2100 PQ に変換できる事が条件です。
そこで簡単なコンバーターを作って対処しました。

EXR をソースとして BT.2100 PQ の色空間に変換して 16bit PNG に保存します。 EXR しか確認していませんが、 Magick.NET でバンドルしている ImageMagick で読めるソースだったらなんでもいけるはずです。

出力される PNG は ICC が含まれるわけではないので厳密には正しくないのですが、 cavif/avifenc は画像データー部分しか見ないので中間ソースとしては特に問題ないわけです。

ちなみに単純な 0.0~1.0 のリニアグラデーションを BT.2100 PQ に変換したものを sRGB の画像として見ると次のようになります。

暗いのは当然として色が浅く見えるので色域が合っていないのがよくわかります。

AVIF に変換する

ここでは avifenc を使用します。

ビルド

最低限 CMake と NASM が必要ですが組み合わせるデコーダー、エンコーダーによっては Meson, Ninja, cargo (Rust) が必要になります。 "Build Notes" を確認して必要なものをインストールしてください。

次に ext ディレクトリに移動して外部ライブラリのビルドをします。

$ cd ext
$ ./zlibpng.cmd
$ ./aom.cmd      
$ ./dav1d.cmd    
$ ./rav1e.cmd    

zlibpng は必須、他は組み合わせによりますが aom はデコーダー/エンコーダーの両方、 dav1d はデコーダー、 rav1e はエンコーダーです。

$ cd ..
$ mkdir build
$ cd build
$ cmake .. -DAVIF_CODEC_AOM=ON -DAVIF_LOCAL_AOM=ON -DAVIF_CODEC_DAV1D=ON -DAVIF_LOCAL_DAV1D=ON -DAVIF_CODEC_RAV1E=ON -DAVIF_LOCAL_RAV1E=ON -DBUILD_SHARED_LIBS=OFF -DAVIF_LOCAL_JPEG=1 -DAVIF_LOCAL_ZLIBPNG=1 -DAVIF_BUILD_APPS=ON
$ make

使用しないコーデックは OFF にしておけば事前ビルドも不要です。

変換する

HDR 向けの設定です。

$ avifenc src.png -d 10 -y 420 --cicp 9/16/9 --min 0 --max 0 dst.avif
  • -d → ビット深度 (10 or 12)
  • -y → YUV フォーマット (420 or 422 or 444)
  • --cicp → 9/16/9 の固定で
  • --min → 量子化パラメーター (最小)
  • --max → 量子化パラメーター (最大)

YUV フォーマットについては詳細はここでは省きます。通常は 420 で問題ないはずですが、劣化させたくない場合は 444 で。

--min, --max は値が大きい程画質が悪くなって 0 はロスレスです。

AVIF を表示してみる

最初の方で書きましたが、現在の Chrome は画像フォーマットとして AVIF に対応していて、 HDR での表示にも対応しています。加えて HTML の img タグでのソースにも指定できるので Youtube 以外の方法で HDR コンテンツを Web 上に公開することが可能 になっていることになります。

テスト画像を用意しました。 HDR ディスプレイ出力に対応している環境の Chrome で開いてみてください。

https://twitter.com/TANY_FMPMD/status/1368551115403358208?s=20

これは Unity で HDR レンダリングしたものをキャプチャして AVIF にしたものです。これは SDR 化する Tonemapping を無効化することにより HDR 映像としてレンダリングされています。これをそのまま SDR で見ると単純なクリッピングになって綺麗に見えませんので HDR 環境で確認してください。

Magick.NET を使ったプログラミング

本題よりちょっと脱線ですが。

Magick.NET は ImageMagick の C# ラッパーライブラリで様々な静止画フォーマットを簡単に扱うことができます。どれくらい簡単かは サンプルコード を見てもらえれば分かるかと思います。もっと簡単にするとこれくらいには。

https://twitter.com/TANY_FMPMD/status/1362422892529553409?s=20

ちょっとひっかかったのがピクセル値の扱い。 ImageMagick は扱うイメージのピクセル精度毎にバイナリが分かれている (Q8 / Q16 / Q16-HDRI) ようです。今回は HDR を扱うので Q16-HDRI を選択しました。

MagickImage.GetPixels が返す型が IPixelCollection<float> 、つまり float 精度なのですが、実際の値の範囲が 0.0~1.0 ではなく 0.0~65535.0 のようです。オリジナルの ImageMagick のドキュメントを見ても Q16 は uint16 のことのようなのですが、 Magick.NET では float になっているようです (ちなみに Q8 のパッケージにすると byte になります) 。この点は注意が必要なのと、精度面で問題が出るかもしれません。

おわりに

AVIF はエンコード、デコードも (まだ若干面倒ですが) 行うことができ、 Chrome が HDR 含めて対応しているので、普通に HDR 静止画像をブラウザ上で扱える段階になってきていると思います。 Android 12 でもサポートされるようです。

従来であれば RAW で撮影した写真や HDR でレンダリングした CG などは結局 SDR に変換しなければならなかったですが、 HDR の AVIF にすることでよりマスターに近い映像を Web 上に載せることができるようになりました。今後の標準化、普及に期待したいところです。

Discussion