LoginSignup
6
5

ImageMagick と HEIF 画像

Last updated at Posted at 2022-01-29

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 コーデックに指示を出します。

coders/heic.c
    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
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 として値を渡します。

こちらの記事によると --cpu-used で 1〜8 を指定できて、1 が画質優先、8が処理速度優先でトレードオフになるようです。

備考

ライセンス

HEIF/HEVC は画像データをエンコードするのに H.265/HEVC エンコーダを利用します。
何かのサービスで H.265/HEVC エンコーダを使いたい場合、そのエンコーダ自体のライセンスもそうですが、それとは別に、H.265/HEVC を使うライセンスも意識する必要があります。

以下のサイトを参考にどうぞ。

H.265/HEVC の特許ライセンスを持つ会社が沢山あり、ライセンスプールに全てまとめようとしたが、納得いかない会社が各々ライセンスプールを独自に作って複数存在するので、各々交渉するのが大変そうです。

iloc offset 問題

iloc の baseOffset, extendOffset の使い方の問題で、ImageMagick (というより libheif) で作った HEIF ファイルが読めないアプリケーションがたまにあります。古いバージョンの LightRoom とか。

トラブルがあった時には思い出すと良いかもしれません。

当初のゴタゴタ

ImageMagick は 2017年に立候補する人が現れ、2018年1月に対応しました。当時は libde265 のみ依存して、コンテナ処理を全部自前で実装していました。あと読み込みしか出来ません。

正直なところあまり品質の良ろしく無い実装だったのと、libheif が世に出た事により、それまでの実装を全部なかった事にして、ImageMagick のコア開発者が libheif を使った実装で1から作り直し 2018年5月にリリースされてます。

また libheif は途中から書き出しにも対応したので、ImageMagick もそれに合わせて HEIF 書き出しが可能になりました。更に、この後、libheif は AVIF にも対応したので大変ラッキー。HEIF と AVIF をどちらも ISOBMFF コンテナで情報要素が似ているので、もしかしたらという期待はありました。

そんな訳で、2018年前半の HEIF 対応と 2018年中旬以降の HEIF 対応は全く別物です。

参考 URL

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5