2023-08-09

ImageMagick vs GraphicsMagick vs FFmpeg (Emacsのimage-converter変数にはどれを指定すべきか)

Emacs 29からGraphicsMagick対応が入りました。image系の機能でImageMagick(convertコマンド)を使う箇所がGraphicsMagick(gmコマンド)にも対応した形です。

早速試してみたのですが、image-diredでmp4ファイルのサムネイルが表示できなくなってしまいました(image-diredで多様なファイル形式を扱うには確か色々設定が必要だったと思うのですが、それはまた別の機会に)。どうもImageMagickとGraphicsMagickでは対応している形式に差があるようです。

というわけで、具体的にどのような差があるのか調べてみました。Emacsにはimage-converterという仕組みがあって、Emacsが標準で対応していない形式の画像でも外部のコンバーターを使用して変換し、表示することが出来ます。image-converter.elの中で定義されている image-converter--probe 関数は指定されたコンバーターがサポートする形式をリストアップします。それを使ってみました。

ImageMagickが対応する形式:

(setq image-converter--converters
  '((graphicsmagick :command ("gm" "convert") :probe ("-list" "format"))
    (ffmpeg :command "ffmpeg" :probe "-decoders")
    (imagemagick :command ("magick" "convert") :probe ("-list" "format")))) ;; magickコマンドを使うように修正する(WindowsだとSystem32にconvert.exeがあるので)
(setq im-formats (image-converter--probe 'imagemagick))
("3fr" "3g2" "3gp" "aai" "ai" "apng" "art" "arw" "avi" "avif" "avs" "bayer"
 "bayera" "bgr" "bgra" "bgro" "bie" "bmp" "bmp2" "bmp3" "cal" "cals" "canvas"
 "caption" "cin" "clip" "clipboard" "cmyk" "cmyka" "cr2" "cr3" "crw" "cube"
 "cur" "cut" "data" "dcm" "dcr" "dcraw" "dcx" "dds" "dfont" "djvu" "dng"
 "dpx" "dxt1" "dxt5" "emf" "epdf" "epi" "eps" "epsf" "epsi" "ept" "ept2"
 "ept3" "erf" "farbfeld" "fax" "ff" "file" "fits" "fl32" "flif" "flv"
 "fractal" "ftp" "fts" "ftxt" "g3" "g4" "gif" "gif87" "gradient" "gray"
 "graya" "group4" "hald" "hdr" "heic" "heif" "hrz" "http" "https" "icb" "ico"
 "icon" "iiq" "inline" "ipl" "j2c" "j2k" "jbg" "jbig" "jng" "jnx" "jp2" "jpc"
 "jpe" "jpeg" "jpg" "jpm" "jps" "jpt" "k25" "kdc" "label" "m2v" "m4v" "mac"
 "map" "mask" "mat" "mef" "miff" "mkv" "mng" "mono" "mov" "mp4" "mpc" "mpeg"
 "mpg" "mpo" "mrw" "msl" "msvg" "mtv" "mvg" "nef" "nrw" "null" "orf" "otb"
 "otf" "pal" "palm" "pam" "pango" "pattern" "pbm" "pcd" "pcds" "pcl" "pct"
 "pcx" "pdb" "pdf" "pdfa" "pef" "pes" "pfa" "pfb" "pfm" "pgm" "pgx" "phm"
 "picon" "pict" "pix" "pjpeg" "plasma" "png" "png00" "png24" "png32" "png48"
 "png64" "png8" "pnm" "pocketmod" "ppm" "ps" "psb" "psd" "ptif" "pwp" "qoi"
 "raf" "ras" "raw" "rgb" "rgb565" "rgba" "rgbo" "rgf" "rla" "rle" "rmf"
 "rsvg" "rw2" "scr" "sct" "sfw" "sgi" "six" "sixel" "sr2" "srf" "stegano"
 "strimg" "sun" "svg" "svgz" "text" "tga" "tiff" "tiff64" "tile" "tim" "tm2"
 "ttc" "ttf" "txt" "uyvy" "vda" "vicar" "vid" "viff" "vips" "vst" "wbmp"
 "webm" "webp" "wmf" "wmv" "wpg" "x3f" "xbm" "xc" "xcf" "xpm" "xps" "xv"
 "ycbcr" "ycbcra" "yuv" "r")

ちなみに処理に9.3秒もかかりました。何にそんなにかかっているんだろう。

次いでGraphicsMagickが対応する形式:

(setq gm-formats (image-converter--probe 'graphicsmagick))
("3fr" "8bim" "8bimtext" "8bimwtext" "app1" "app1jpeg" "art" "arw" "avif"
 "avs" "b" "bie" "bigtiff" "bmp" "c" "cals" "caption" "cin" "clipboard"
 "cmyk" "cmyka" "cr2" "crw" "cur" "cut" "dcm" "dcr" "dcx" "dng" "dpx" "emf"
 "epdf" "epi" "eps" "epsf" "epsi" "ept" "ept2" "ept3" "erf" "exif" "fax"
 "file" "fits" "fractal" "g" "gif" "gif87" "gradient" "gray" "graya" "heic"
 "heif" "hrz" "http" "icb" "icc" "icm" "ico" "icon" "identity" "image" "iptc"
 "iptctext" "iptcwtext" "j2c" "jbg" "jbig" "jng" "jnx" "jp2" "jpc" "jpeg"
 "jpg" "k" "k25" "kdc" "label" "m" "mac" "map" "mat" "mef" "miff" "mng"
 "mono" "mpc" "mrw" "msl" "mtv" "mvg" "nef" "null" "o" "orf" "otb" "p7" "pal"
 "palm" "pam" "pbm" "pcd" "pcds" "pct" "pcx" "pdb" "pdf" "pef" "pfa" "pfb"
 "pgm" "pgx" "picon" "pict" "pix" "plasma" "png" "png00" "png24" "png32"
 "png48" "png64" "png8" "pnm" "ppm" "ps" "ptif" "pwp" "r" "raf" "ras" "rgb"
 "rgba" "rla" "rle" "sct" "sfw" "sgi" "sr2" "srf" "stegano" "sun" "svg"
 "svgz" "text" "tga" "tiff" "tile" "tim" "topol" "ttf" "txt" "uyvy" "vda"
 "vicar" "vid" "viff" "vst" "wbmp" "webp" "wmf" "wmfwin32" "wpg" "x3f" "xbm"
 "xc" "xcf" "xmp" "xpm" "xv" "y" "yuv")

こちらは3.3秒です。

対応フォーマット数の比較:

(list (list "ImageMagick" "GraphicsMagick")
      'hline
      (list (length im-formats) (length gm-formats)))
ImageMagick GraphicsMagick
238 172

どちらにもあるもの:

(seq-intersection im-formats gm-formats)
("3fr" "art" "arw" "avif" "avs" "bie" "bmp" "cals" "caption" "cin"
 "clipboard" "cmyk" "cmyka" "cr2" "crw" "cur" "cut" "dcm" "dcr" "dcx" "dng"
 "dpx" "emf" "epdf" "epi" "eps" "epsf" "epsi" "ept" "ept2" "ept3" "erf" "fax"
 "file" "fits" "fractal" "gif" "gif87" "gradient" "gray" "graya" "heic" "heif"
 "hrz" "http" "icb" "ico" "icon" "j2c" "jbg" "jbig" "jng" "jnx" "jp2" "jpc"
 "jpeg" "jpg" "k25" "kdc" "label" "mac" "map" "mat" "mef" "miff" "mng" "mono"
 "mpc" "mrw" "msl" "mtv" "mvg" "nef" "null" "orf" "otb" "pal" "palm" "pam"
 "pbm" "pcd" "pcds" "pct" "pcx" "pdb" "pdf" "pef" "pfa" "pfb" "pgm" "pgx"
 "picon" "pict" "pix" "plasma" "png" "png00" "png24" "png32" "png48" "png64"
 "png8" "pnm" "ppm" "ps" "ptif" "pwp" "raf" "ras" "rgb" "rgba" "rla" "rle"
 "sct" "sfw" "sgi" "sr2" "srf" "stegano" "sun" "svg" "svgz" "text" "tga"
 "tiff" "tile" "tim" "ttf" "txt" "uyvy" "vda" "vicar" "vid" "viff" "vst"
 "wbmp" "webp" "wmf" "wpg" "x3f" "xbm" "xc" "xcf" "xpm" "xv" "yuv" "r")

これらはどちらでもサポートされます。

ImageMagickにだけあるもの:

(seq-difference im-formats gm-formats)
("3g2" "3gp" "aai" "ai" "apng" "avi" "bayer" "bayera" "bgr" "bgra" "bgro"
 "bmp2" "bmp3" "cal" "canvas" "clip" "cr3" "cube" "data" "dcraw" "dds"
 "dfont" "djvu" "dxt1" "dxt5" "farbfeld" "ff" "fl32" "flif" "flv" "ftp" "fts"
 "ftxt" "g3" "g4" "group4" "hald" "hdr" "https" "iiq" "inline" "ipl" "j2k"
 "jpe" "jpm" "jps" "jpt" "m2v" "m4v" "mask" "mkv" "mov" "mp4" "mpeg" "mpg"
 "mpo" "msvg" "nrw" "otf" "pango" "pattern" "pcl" "pdfa" "pes" "pfm" "phm"
 "pjpeg" "pocketmod" "psb" "psd" "qoi" "raw" "rgb565" "rgbo" "rgf" "rmf"
 "rsvg" "rw2" "scr" "six" "sixel" "strimg" "tiff64" "tm2" "ttc" "vips" "webm"
 "wmv" "xps" "ycbcr" "ycbcra")

GraphicsMagickにだけあるもの:

(seq-difference gm-formats im-formats)
("8bim" "8bimtext" "8bimwtext" "app1" "app1jpeg" "b" "bigtiff" "c" "exif" "g"
 "icc" "icm" "identity" "image" "iptc" "iptctext" "iptcwtext" "k" "m" "o"
 "p7" "topol" "wmfwin32" "xmp" "y")

うーん、やはりmp4など動画系のファイルはImageMagickじゃないと対応していないみたいですね。GraphicsMagick Supported Formatsを見てもmp4はありません。地味にpsdがImageMagickのみというのは大きいです。

ということで私はImageMagickを使うように戻しました。Windowsだとinit.elに多少ごちゃごちゃ書かないといけませんが、その程度は我慢します。GraphicsMagickに対応する前にImageMagick7(magickコマンド)に対応してほしいと思うのは私だけでしょうか……。

ちなみにコンバーターとしてはffmpegも直接指定出来ます。そちらも軽く調べてみましょう。

FFmpegが対応する形式:

(image-converter--probe 'ffmpeg)
("012v" "4xm" "8bps" "aasc" "agm" "aic" "alias_pix" "amv" "anm" "ansi" "apng"
 "arbc" "argo" "asv1" "asv2" "aura" "aura2" "libdav1d" "libaom" "av1"
 "av1_cuvid" "av1_qsv" "avrn" "avrp" "avs" "avui" "ayuv" "bethsoftvid" "bfi"
 "binkvideo" "bintext" "bitpacked" "bmp" "bmv_video" "brender_pix" "c93"
 "cavs" "cdgraphics" "cdtoons" "cdxl" "cfhd" "cinepak" "clearvideo" "cljr"
 "cllc" "eacmv" "cpia" "cri" "camstudio" "cyuv" "dds" "dfa" "dirac" "dnxhd"
 "dpx" "dsicinvideo" "dvvideo" "dxa" "dxtory" "dxv" "escape124" "escape130"
 "exr" "ffv1" "ffvhuff" "fic" "fits" "flashsv" "flashsv2" "flic" "flv" "fmvc"
 "fraps" "frwu" "g2m" "gdv" "gem" "gif" "h261" "h263" "h263i" "h263p" "h264"
 "h264_qsv" "h264_cuvid" "hap" "hdr" "hevc" "hevc_qsv" "hevc_cuvid"
 "hnm4video" "hq_hqa" "hqx" "huffyuv" "hymt" "idcinvideo" "idf" "iff" "imm4"
 "imm5" "indeo2" "indeo3" "indeo4" "indeo5" "interplayvideo" "ipu" "jpeg2000"
 "libopenjpeg" "jpegls" "jv" "kgv1" "kmvc" "lagarith" "loco" "lscr" "m101"
 "eamad" "magicyuv" "mdec" "media100" "mimic" "mjpeg" "mjpeg_cuvid"
 "mjpeg_qsv" "mjpegb" "mmvideo" "mobiclip" "motionpixels" "mpeg1video"
 "mpeg1_cuvid" "mpeg2video" "mpegvideo" "mpeg2_qsv" "mpeg2_cuvid" "mpeg4"
 "mpeg4_cuvid" "msa1" "mscc" "msmpeg4v1" "msmpeg4v2" "msmpeg4" "msp2" "msrle"
 "mss1" "mss2" "msvideo1" "mszh" "mts2" "mv30" "mvc1" "mvc2" "mvdv" "mvha"
 "mwsc" "mxpeg" "notchlc" "nuv" "paf_video" "pam" "pbm" "pcx" "pfm" "pgm"
 "pgmyuv" "pgx" "phm" "photocd" "pictor" "pixlet" "png" "ppm" "prores"
 "prosumer" "psd" "ptx" "qdraw" "qoi" "qpeg" "qtrle" "r10k" "r210" "rasc"
 "rawvideo" "rl2" "roqvideo" "rpza" "rscc" "rv10" "rv20" "rv30" "rv40" "sanm"
 "scpr" "screenpresso" "sga" "sgi" "sgirle" "sheervideo" "simbiosis_imx"
 "smackvid" "smc" "smvjpeg" "snow" "sp5x" "speedhq" "srgc" "sunrast"
 "librsvg" "svq1" "svq3" "targa" "targa_y216" "tdsc" "eatgq" "eatgv" "theora"
 "thp" "tiertexseqvideo" "tiff" "tmv" "eatqi" "truemotion1" "truemotion2"
 "truemotion2rt" "camtasia" "tscc2" "txd" "ultimotion" "utvideo" "v210"
 "v210x" "v308" "v408" "v410" "vb" "vble" "vbn" "vc1" "vc1_qsv" "vc1_cuvid"
 "vc1image" "vcr1" "xl" "vmdvideo" "vmnc" "vnull" "vp3" "vp4" "vp5" "vp6"
 "vp6a" "vp6f" "vp7" "vp8" "libvpx" "vp8_cuvid" "vp8_qsv" "vp9" "libvpx"
 "vp9_cuvid" "vp9_qsv" "vqc" "wbmp" "wcmv" "webp" "wmv1" "wmv2" "wmv3"
 "wmv3image" "wnv1" "wrapped_avframe" "vqavideo" "xan_wc3" "xan_wc4" "xbin"
 "xbm" "xface" "xpm" "xwd" "y41p" "ylc" "yop" "yuv4" "zerocodec" "zlib"
 "zmbv")

数こそ多いもののやはり動画系が中心のようです。画像コンバーターとしてffmpegだけを指定するのはあまりおすすめ出来なそうです。

全部のコンバーターを切り替えて使えば良さそうにも思えますが、基本的にはimage-converter.elはそのようには出来ていないようです。image-converter-add-handler関数を使って逐一登録すればおそらく可能だとは思いますが。


余談ですが、とうとう長年使っていたCygwinを止めてMSYS2に統一しました。FFmpegやGraphicsMagickもパッケージとして登録されていますし。ノートPCの方ではMSYS2だけにしていて特に問題が無かったので。EmacsもMSYS2のを使えば良いかなと思っていたのですが、先日MSYS2版のEmacsにトラブルがあって以来、ノートPCの方でも公式ビルドを使っています。

image-diredでDiredの中に多様な形式の画像をサムネイル表示する方法についてですが、Emacs起動直後には標準で対応している形式しか表示できず、コンバーターを一回でも使った後は表示できるようになるようです(何か私がおかしな設定をしているのでなければ)。これは、image-diredが表示できる形式かどうかを (image-file-name-regexp) が返す正規表現でチェックしているからです。image-file-name-regexp関数は内部でimage-converter-file-name-extensionsという変数を参照しているのですが、その変数は何かimage-converter.el内の関数を呼ぶまでnilのままだからです。init.elで呼び出して初期化してやろうにも、上記の通り9秒もかかったりするのでおいそれとはできません。まぁ、その辺りがちゃんと初期化していない理由なのかもしれません。手動で必要な拡張子だけinit.elで設定するのが現実的かもしれません。