SVG を TikZ ソースに変換する Docker コンテナを作る

以前，SVG 画像 → TikZ ソース の変換をテーマとした[記事](https://doratex.hatenablog.jp/entry/20140422/1398132985)を書きました。

* [Illustratorで描いた図をTikZに変換 - TeX Alchemist Online](https://doratex.hatenablog.jp/entry/20140422/1398132985)

ただしこの記事を書いたのはもう5年半も前。Python 2.7 を使っているあたりが，時代を感じさせますね。あれから随分時間が経ち，当時とは状況が色々変わりました。現状がどうなっているかを調べました。

当時利用した [kjellmf 氏の svg2tikz レポジトリ](https://github.com/kjellmf/svg2tikz)は，その後 Python 3 に対応するようアップデートされていました。ただし，依然として Python 2 にも対応しているそうです。ですがこのレポジトリは `UNMAINTAINED` とラベリングされており，今や開発は停滞しているようです。

また，[paaguti 氏の svg2tikz レポジトリ](https://github.com/paaguti/svg2tikz)もありました。これは同名ですが全く別物のようです。これは現在 Python 3 のみをサポート対象としています。

よって，現在は SVG → TikZ 変換の方法としては，以下の3通りがあることになります。

1. kjellmf 氏の svg2tikz を Python 2 で使う。
2. kjellmf 氏の svg2tikz を Python 3 で使う。
3. paaguti 氏の svg2tikz を Python 3 で使う。

実験してみたところ，これらは一長一短で，「得意な SVG と苦手な SVG がある」感じで，単純に優劣は付けにくいようでした。

たとえば，svg2tikz 氏の svg2tikz レポジトリに付属のサンプル図版 [tikz.svg](https://github.com/paaguti/svg2tikz/blob/master/tikz.svg)，および5年前の記事で用いた [MagneticStirrer.svg](https://gist.github.com/doraTeX/724bc11408dcd16836cbb7f63d66be88) のそれぞれを変換してみたところ，次のような結果となりました。

|                              | tikz.svg | MagneticStirrer.svg |
|-------------------------------|----------|---------------------|
| kjellmf's svg2tikz on Python 2 | ○        | ◎                   |
| kjellmf's svg2tikz on Python 3 | ○        | ×                   |
| paaguti's svg2tikz on Python 3 | ◎        | ×                   |

◎＝綺麗に変換できた
○＝見た目が一部変わってしまったが変換できた
×＝エラーが出て変換不能

この結果を見ると，意外にも，5年前の古い時代と同じ Python 2 を用いた第一の手法が安定していそうな感触でした。

しかし，2020年1月1日にもサポート終了を迎え，残り寿命が3日と迫った Python 2 の環境を，この変換のためだけに今更整えるというのも後ろ向きで気が引けます。こういうときこそ Docker の出番でしょう。

というわけで，

* Alpine Linux
* Python 2.7
* Python 2 用 lxml ライブラリ
* [kjellmf 氏の svg2tikz](https://github.com/kjellmf/svg2tikz) のうち必要最小限のファイル
* その起動用ラッパースクリプト

をコンテナ化した Docker イメージを用意しました。

# 使い方

完成したイメージは Docker Hub に [doratex/svg2tikz](https://hub.docker.com/repository/docker/doratex/svg2tikz) としてアップロードしてあるので，

```sh
$ docker pull doratex/svg2tikz
```

とすれば pull できます。

コンテナ内では `/workdir` が作業ディレクトリとなるので，それをカレントディレクトリと bind マウントして使うのを想定しています。

```bash
alias svg2tikz="docker run --rm \
  --mount type=bind,src=\"\$(pwd)\",dst=/workdir \
  doratex/svg2tikz"
```

などとエイリアスを設定しておくと楽でしょう。このエイリアスが設定されている下で

```sh
$ svg2tikz sample.svg -o sample.tex
```

とすれば，SVG 図版を TikZ ソースに変換できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41739/2b890277-16b7-7e1f-58e6-aeab66443d02.png)

とてもいい感じに変換できていますね！

# Dockerfile

このイメージを作成するために用意した Dockerfile は以下の通りです。

```dockerfile:Dockerfile
FROM python:2.7.11-alpine

LABEL maintainer="doraTeX <taylorkgb [at] gmail.com>"

WORKDIR /workdir

ENV TEMPORARY_DEPS \
    gcc \
    ca-certificates \
    openssl \
    libc-dev \
    libxml2-dev 

ENV PERSISTENT_DEPS \
    libxslt-dev

ENV SVG2TIKZ_REPO \
    https://raw.githubusercontent.com/kjellmf/svg2tikz/master/svg2tikz

RUN apk upgrade --update
RUN apk add --no-cache --virtual .persistent-deps ${PERSISTENT_DEPS}
RUN apk add --no-cache --virtual .temporary-deps ${TEMPORARY_DEPS} && \
    pip install lxml && \
    mkdir /svg2tikz && \
    cd /svg2tikz && \
    wget -q ${SVG2TIKZ_REPO}/inkexlib/inkex.py && \
    wget -q ${SVG2TIKZ_REPO}/inkexlib/simplestyle.py && \
    wget -q ${SVG2TIKZ_REPO}/inkexlib/simplepath.py && \
    wget -q ${SVG2TIKZ_REPO}/extensions/tikz_export.py && \
    cd /usr/local/bin && \
    printf "%s\n" \
      "#!/bin/sh" \
      "EXEC='python -B /svg2tikz/tikz_export.py'" \
      "if [ \$# -eq 0 ]; then " \
      "  \${EXEC} --help" \
      "else" \
      "  \${EXEC} \"\$@\"" \
      "fi" \
      > svg2tikz && \
    chmod +x svg2tikz && \
    apk del .temporary-deps

ENTRYPOINT ["svg2tikz"]
```