2022-04-06

Windows上のEmacsでSVG画像内のimage要素が表示されない問題

Emacs27になってからSVG画像内のimage要素が表示されなくて困ったのですが、調べたところ lib/gdk-pixbuf-2.0/2.10.0/loaders.cache ファイルが無いのが原因だと分かりました。

いずれも Index of /gnu/emacs/windows にある公式のWindows版ビルドでの話です。独自ビルドして必要そうなDLLファイルをMinGWから抜き出した場合も起こるかもしれません。

表示されないSVGの例

例えば次のようなSVGでimage要素の部分が表示されずblueのrectだけが表示されます。

<svg width="400" height="300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  <rect x="10px" y="10px" width="100px" height="80px" fill="blue" />
  <image xlink:href="image1.jpg" x="20px" y="20px" width="100px" height="100px" />
  <image xlink:href="image2.png" x="30px" y="30px" width="100px" height="100px" />
  <image xlink:href="image3.bmp" x="40px" y="40px" width="100px" height="100px" />
</svg>

image1.jpgimage2.pngimage3.bmp はSVGと同じディレクトリにあるものとします。もちろんブラウザ等、他のソフトウェアでは正しく表示されます。Emacsでの確認方法は色々ありますがdiredから開くだけでも十分です。

Emacs 26.3の場合

https://ftp.gnu.org/gnu/emacs/windows/emacs-26/emacs-26.3-x86_64.zip

問題は起きません。正しく表示されます。

Emacs 27.2の場合

解決方法

cmdプロンプトで emacs-27.2-x86_64/bin ディレクトリへ移動し、次のコマンドを実行すると emacs-27.2-x86_64/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache というファイルが生成されます。

gdk-pixbuf-query-loaders.exe --update-cache

Emacsを再起動して再び試してみると正しく表示されました。

Emacs 28.1の場合

https://ftp.gnu.org/gnu/emacs/windows/emacs-28/emacs-28.1.zip

image要素が表示されません。

解決方法

そもそも emacs-28.1/lib/ 以下に gdk-pixbuf-2.0 がありません。

Emacs27のファイル(emacs-27.2-x86_64/lib/gdk-pixbuf-2.0 以下。もちろん loaders.cache も)をEmacs28へコピーしたところ正しく表示されました。

loaders.cache を削除すると正しく表示されないので、Emacs28でもこのファイルは必要なようです。 emacs-28.1.zip には gdk-pixbuf-query-loaders.exe が含まれていないので、生成するにはEmacs 27の場合の手順を踏んでそちらからコピーしてくるのが手っ取り早いと思います。

原理

EmacsはSVGの描画にlibrsvgを使用していますが、librsvgは画像の処理にlibgdk_pixbufを使用しています。

libgdk_pixbufで画像を読み込むには画像の形式に対応するローダーライブラリが必要で、それが lib/gdk-pixbuf-2.0/2.10.0/loaders/ 以下にあるDLLファイル群です。

loaders.cache ファイルには、DLLファイルへのパスとそれが受け付けるMIMEタイプ、拡張子、ファイル先頭のマジックナンバー等の対応表が記されているようです。詳しくは調べていませんが、このファイルが無いとlibgdk_pixbufは画像を読み込めないようです。

不思議なことにEmacs26はこのファイルが無くても正しく読み込めていました。おそらくライブラリのバージョンアップに伴って必要になったのではないでしょうか。

必要性

EmacsでSVG内のimage要素、それもWindowsで扱う必要がある人はどれだけいるのでしょうか。多分ほとんどの人が問題に気がついていないのだと思います(まさか私の環境だけ起きてる?)。

しかしsvg.elにはsvg-embedのようなimage要素を使う機能も存在します。

また、Emacs28ではSVG内のimage要素が外部ファイルを参照する時の基準ディレクトリを指定する機能も追加されました。(https://github.com/emacs-mirror/emacs/blob/78ecd67888566167fb4c881d8350f611fa039649/etc/NEWS.28#L2417 )

図形だけでも面白いのに画像を自由に配置できるとなればもっと面白いことが色々出来るはずです。皆さんも是非試してみてはいかがでしょうか。

私も試しにimage要素を沢山生成して遊んでみました。

2022-04-06-svg-image-ex.gif

一枚一枚の画像をtransform属性で変形し(残念ながら透視投影は無理なので正射影です)、面単位でZソートを行っています。

結構遅いです。

何となくEmacs Lisp側というよりは描画ライブラリ側が遅いような気が。

Pingback / Trackback