HEIF / HEIC
HEIF は主に H.265/HEVC のエンコーダを使って画像をファイル化します。
ただ、HEIF 自体は H.264/AVC や JPEG 等も入れられる汎用画像コンテナフォーマット規格です。
そこで H.265/HEVC の画像が含まれる事を示すのに HEIC の呼称があり、拡張子によく使われます。ImageMagick における HEIF のコーダー名は HEIC です。
ImageMagick の HEIF 対応
2018年5月リリースの ImageMagick-7.0.7-32 (6系は 6.9.9-44) で HEIF 画像に対応しました。
実はその前に、2018年1月の ImageMagick-7.0.7-22 で HEIF 対応したのですが、色々と問題があり、その実装はなかった事にして、libheif の利用を前提にいちから作り直してます。(詳しくは後述)
HEIF 対応か調べる
ImageMagick で HEIF を扱うには、libheif が入っている環境でビルドする必要があります。手元の ImageMagick が対応しているかは以下のコマンドで分かります。
% convert -list format | grep HEIC
AVIF* HEIC rw+ AV1 Image File Format (1.12.0)
HEIC* HEIC rw+ High Efficiency Image Format (1.12.0)
HEIF* HEIC rw+ High Efficiency Image Format (1.12.0)
% convert -list coder | grep HEIC
AVIF HEIC
HEIF HEIC
ビルドする場合、configure 実行時に以下のように認識されれば HEIF 入出力機能を組み込めます。
./configure
(略)
checking for libheif... yes
(略)
HEIC --with-heic=yes yes
使い方
特に他のファイル形式と変わりません。
% identify IMG_0001.HEIC # ← iPhone カメラで撮った写真
IMG_0001.HEIC HEIC 806x605 806x605+0+0 8-bit sRGB 0.000u 0:00.001
% convert IMG_0001.HEIC 0001.jpg
% convert rose: rose.heic
Lossless
ちなみに、ImageMagick は -quality 100 で Lossless (劣化無し) だと HEIF コーデックに指示を出します。
lossless=image_info->quality == 100 ? MagickTrue : MagickFalse;
chroma=lossless ? heif_chroma_444 : heif_chroma_420;
(略)
if (lossless != MagickFalse)
error=heif_encoder_set_lossless(heif_encoder,1);
試してみると。。。バグってますね。(┐「ε:) (ImageMagick 7.1.0-2, libheif-1.12.0)
% convert lena_std.png -quality 100 lena_im.heic
% convert lena_im.heic im.png
lena_std.png | im.png |
---|---|
生成された HEIF コンテナを覗くと YUV420 ですし、libheif の使い方を間違っていそうです。
実装
libheif を使って HEIF の入出力をします。libheif はコンテナを扱うライブラリで、実画像データの H.265 エンコード/デコードは x265/libde265 を使います。
なお、libheif の AVIF 対応に便乗して ImageMagick も AVIF に対応しました。HEIF/AVIF どちらの実装も coders/heic.c に含まれます。
オプション指定
heic:preserve-orientation
true で回転方向を維持します。これに false を入れると exif:Orientation が 1 に上書きされます。
heic:depth-image
これを true にすると Depthデータを複数画像の1つとして取り出せるはずです。(手元にデータがないので試せない)
heic:chroma
libheif 越しに aom/rav1e, x265 といったエンコーダに渡す(はずの)パラメータです。
libheif/heif_encoder_x265.cc を見ると "420", "422", "444" の3つから選べるはずですが、実際に試すと全部 420 として HEIF 変換されました。これ以外の文字列を渡してもエラーにならないので、おそらく libheif に渡してなさそうです。
なお、AVIF では指定した chroma subsampling で変換されました。libaom にはちゃんと渡ってます。
heic:speed
speed は AVIF で有効なオプションで、AV1 エンコーダの aom もしくは rav1e に cpu_used として値を渡します。
- aomencのオプション
こちらの記事によると --cpu-used で 1〜8 を指定できて、1 が画質優先、8が処理速度優先でトレードオフになるようです。
heic:chroma-downsampling (2024-02-14 追加機能)
クロマサブサンプリングの方式を選択できます。libheif 1.16 以降が必要です。
- nearest-neighbor
- average
- sharp-yuv
YUV444 を YUV420 に落とすと彩度が落ちがちですが、なるべく残してくれる WebP でお馴染みの sharp-yuv 機能が使えます。
備考
ライセンス
HEIF/HEVC は画像データをエンコードするのに H.265/HEVC エンコーダを利用します。
何かのサービスで H.265/HEVC エンコーダを使いたい場合、そのエンコーダ自体のライセンスもそうですが、それとは別に、H.265/HEVC を使うライセンスも意識する必要があります。
以下のサイトを参考にどうぞ。
- H.265/HEVC特許暗黒時代
H.265/HEVC の特許ライセンスを持つ会社が沢山あり、ライセンスプールに全てまとめようとしたが、納得いかない会社が各々ライセンスプールを独自に作って複数存在するので、各々交渉するのが大変そうです。
iloc offset 問題
iloc の baseOffset, extendOffset の使い方の問題で、ImageMagick (というより libheif) で作った HEIF ファイルが読めないアプリケーションがたまにあります。古いバージョンの LightRoom とか。
- https://github.com/ImageMagick/ImageMagick/issues/1790
- https://feedback-readonly.photoshop.com/conversations/camera-raw-and-dng/camera-rawlightroom-support-additional-flavors-of-heic/5f5f46234b561a3d42758957
トラブルがあった時には思い出すと良いかもしれません。
当初のゴタゴタ
ImageMagick は 2017年に立候補する人が現れ、2018年1月に HEIC 実装が入りました。当時は libde265 のみ依存して、コンテナ処理を全部自前で実装していました。あと読み込みonlyです。
- ImageMagick-6.9.9-34差分
コンテナ構造を決めうち処理して iPhone が出力する HEIC のみ動作する、あまり融通の効かない実装のまま改善する気配がなかったのと、libheif が世に出た事により、それまでの実装を全部差し替えて、ImageMagick のコア開発者が libheif を使った実装で1から作り直し 2018年5月にリリースされてます。
- ImageMagick-6.9.9-44差分
また libheif は途中から書き出しにも対応したので、ImageMagick もそれに合わせて HEIF 書き出しが可能になりました。更に、この後、libheif が AVIF にも対応したので、少ない手間での AVIF 対応が可能になっています。
HEIF と AVIF どちらも ISOBMFF コンテナで情報要素が似ているので、もしかしたらという期待はありましたが、大変ラッキーです。
そんな訳で、2018年前半の HEIF 対応と 2018年中旬以降の HEIF 対応は全く別物です。
- https://github.com/ImageMagick/ImageMagick/issues/507
- https://github.com/ImageMagick/ImageMagick/issues/997