Zenn
🖼️

iOS18のHEIC画像は古いImageMagickだと読めない

に公開

zennでは1ツイートにぎゅうぎゅうに詰め込んだ技術的な話のもうちょっと詳しい話を書いていきます。今日はこれです。

https://x.com/acidlemon/status/1902428282488025131

最近、プライベートの時間ではHugoをいろいろいじってて、テーマとかShortcodeをいろいろいじってるとよくできた仕組みだなあと感心しています(近況)。

それはさておき、iPhoneで写真を撮ると、結構前からHEICというファイル形式で保存されるようになりました。JPEGとかよりも画質がよくて圧縮率も高いらしいです。

ただ、HEICな画像は <img src="powawa.HEIC" alt="ぽわわ"/> のように書いてもたいていのブラウザでは表示できません。caniuseで調べてみると、一応Safari 17からだけサポートされているようです。

ということで、最終的にwebpとかにしていくにしても、一旦jpegとかにしちゃったほうが取り回しがよいので、HEICをJPEGに変換するワンライナーを書いてTaskfileに設定しています。

  convert:
    cmds:
      - convert {{ .CLI_ARGS }} -sampling-factor 4:2:0 -quality 85 -interlace JPEG -colorspace sRGB `echo {{ .CLI_ARGS }} | sed s/HEIC/jpeg/`
      - rm {{ .CLI_ARGS}}

こんな感じのを書いておくと、

$ task convert -- path/to/image.HEIC
task: [convert] convert path/to/image.HEIC -sampling-factor 4:2:0 -quality 85 -interlace JPEG -colorspace sRGB `echo path/to/image.HEIC | sed s/HEIC/jpeg/`
task: [convert] rm path/to/image.HEIC

みたいな感じで画像を変換して path/to/image.jpeg ファイルが出来上がります。

HEICからJPEGに変換できないファイルがある

で、めでたいめでたいと思っていたのですが、今日実行したらなんかエラーになってしまいました。

convert-im6.q16: no images defined `path/to/image.jpeg' @ error/convert.c/ConvertImageCommand/3229.

エラーメッセージが親切ではなさすぎる。とりあえず出力ファイル側に問題ありそう? とおもってディレクトリのパーミッションとかも見ましたが、特に問題なし。

とりあえず検索してみますが、見つかるのは /etc/ImageMagick-6/policy.xml の制限に引っかかってると思うよ、みたいな話くらいです。典型的なのはwidth/heightが10000ピクセル以上あると10KPのポリシーに引っかかるという話らしいのですが、お手元の画像は4032x3024だし、ポリシーは16KPになってるのでこの辺の話ではなさそう。

で、convertコマンドには -debugというオプションがあるので、-debug Allとしてエラーの原因を調べます。最後の5行くらいを抜粋するともうちょっと詳しい状況がわかりました。

0:00.027 0.000u 6.9.11 Exception convert-im6.q16[2725308]: heic.c/IsHeifSuccess/119/Exception
  Invalid input: Unspecified: Too many auxiliary image references `path/to/image.HEIC'
0:00.027 0.000u 6.9.11 Cache convert-im6.q16[2725308]: cache.c/DestroyPixelCache/1191/Cache
  destroy
0:00.029 0.000u 6.9.11 Resource convert-im6.q16[2725308]: resource.c/RelinquishMagickResource/1259/Resource
  Map: 1.59123MB/0B/512MiB
0:00.029 0.000u 6.9.11 Exception convert-im6.q16[2725308]: convert.c/ConvertImageCommand/3229/Exception
  no images defined `path/to/image.jpeg'
convert-im6.q16: no images defined `path/to/image.jpeg' @ error/convert.c/ConvertImageCommand/3229.

Invalid input: Unspecified: Too many auxiliary image references ということはやっぱり出力ファイル側じゃなくて入力側の問題ですかね。このメッセージで検索するとそれっぽいIssueがみつかりました。

https://github.com/strukturag/libheif/issues/1190
https://github.com/Imagick/imagick/issues/675

とりあえずiOS18のHEIFはフォーマットがちょっと変わって読めなくなってたようで、libheif 1.18以上にあげればOKということのようです。たしかに、今まで昔のHEIC画像しか変換してなかったので最近iOS18になってからの写真を変換するのは初めてなのでした。

bookwormでlibheifを1.18以降に上げる

私の実行環境はDebian 12 (bookworm)です。検索してみると、bookwormのlibheifは1.15のようです。

https://packages.debian.org/search?searchon=sourcenames&keywords=libheif

bookworm-backportsには1.19が来ているので、これに切り替えればよさそう。

/etc/apt/sources.list にbackportsを追加します。

deb http://ftp.jp.debian.org/debian bookworm-backports main contrib non-free non-free-firmware

apt updateして、libheifのShared Libraryである、libheif1パッケージを入れ換えます。

# apt update
# apt install -t bookworm-backports libheif1
Get:1 http://ftp.jp.debian.org/debian bookworm-backports/main amd64 libheif-plugin-dav1d amd64 1.19.3-1~bpo12+1 [11.3 kB]
Get:2 http://ftp.jp.debian.org/debian bookworm-backports/main amd64 libheif-plugin-libde265 amd64 1.19.3-1~bpo12+1 [15.1 kB]
Get:3 http://ftp.jp.debian.org/debian bookworm-backports/main amd64 libheif1 amd64 1.19.3-1~bpo12+1 [454 kB]
Get:4 http://ftp.jp.debian.org/debian bookworm-backports/main amd64 libheif-plugin-aomenc amd64 1.19.3-1~bpo12+1 [21.4 kB]
Get:5 http://ftp.jp.debian.org/debian bookworm-backports/main amd64 libheif-plugin-x265 amd64 1.19.3-1~bpo12+1 [22.3 kB]

途中で流れるメッセージで、ちゃんとbackportsから1.19系を取ってきてる事も確認できました。

libheif1を入れ換えた後にもう1回convertコマンドで画像変換を試みたところ、無事以前のように変換できました。めでたしめでたし。

Discussion

ログインするとコメントできます