LoginSignup
2
0

More than 5 years have passed since last update.

Go初心者が書くtexファイルをsvgに変換するアプリ

Last updated at Posted at 2019-03-03

はじめに

僕はtexを使ってドキュメントを作ることが少なくないのですが,texでコンパイルした数式や表などを画像として保存したい場面にたまに出くわします (みなさんはそうではないかもしれませんが僕は出くわします).
さて,このようなときに便利なサイトがtexclipです.ここは,ブラウザにtexコードを入力すると画像化してくれる素晴らしいサイトです.
しかしながら,数式が少し間違っていたり(例えば$f_{\mathrm{max}}$を$f_{max}$と間違える),ちょっと表にデータを付け加えたりするとき,再度ブラウザで入力するのがだるくなります.経験上こういうウェブサービスを使うのはちょっとした用途で使うことが多く,どうせもう使わないからと言ってデータを手元に保存しない人がいます (僕).このようなとき,再度ブラウザにデータ入力するのは非常に労力のかかることです.
そこで,どうせならはじめからローカルで書けばいいじゃないかということになります.でも,ローカルで書いたtexファイルの中身をブラウザにコピペするのはやはりめんどくさいので,texclipと同じ機能をもつCLIのアプリがあれば楽になるんじゃなかろうか,ということで作りました.

何を作ったの?

tex2figというCLIアプリ (コマンド) を作りました.
ローカルのtexファイルを画像(.svg)に変換します.
簡単に説明するとtexファイルをtexclipに投げてsvgを取ってくるコマンドです.

特徴

  • Windows, mac, Linuxに対応しています.(Windowsとmacは動作未確認)
  • 実行ファイルで配布しているので,ダウンロードすればすぐに利用できます
  • ウェブ経由で図を作るのでlatex環境がない方でもお使いいただけます
  • ヘッダレスなtexファイルを画像化できます\documentclass{article}とかが不要).

画像化できるtexファイル例:

example.tex
\begin{align*}
e^{i\pi} = -1
\end{align*}
table.tex
\begin{tabular}{c|cc}
       & Col. 1 & Col.2 \\ \hline 
 Row 1 & 1      & 2     \\ 
 Row 2 & a      & b     \\
\end{tabular}

画像化したいところだけ書いて,コマンドに投げるだけで大丈夫です.

僕,無知なの? → はいそうです

  • tex2fig
    完全に同じ名前ですね.この記事を書いているときに知りました.こちらはPythonとlatexで実装されているみたいですね.多分すべてローカルで実行するので,こちらのほうが速いでしょう.

どう使うの?

まず,gitlabからクローンしてください.

使用例

  • svg2fig example.tex: 単一ファイルの画像化
  • svg2fig -d /dir/ table.tex: 保存先を指定して画像化
  • svg2fig -w 20 *.tex: 複数ファイルの画像化

file.texを変換すると-dで指定したディレクトリにfile.svgが生成されます.

オプション

  • -d: 保存先の指定 (default ./)
  • -w: Goroutineの並列数 (default 10)

Go コード

全文は,gitlabを参照してください.コードは非常に簡単です.特に大事そうな部分を説明します.

  • Goroutine, channelを用いた並列処理
    // unpack files with ?Goroutine?
    ch := make(chan string)
    wg := sync.WaitGroup{}
    // make workers
    for i:=0; i<*numWorkers; i++{
        wg.Add(1)
        go tex2Svg(&wg, ch)
    }
    // channel ni fileName wo nagasu
    for _, fileName := range args {
        ch <- fileName
    }
    close(ch)
    wg.Wait()

argsにコマンドラインから受け取ったtexファイル名が入っています.この並列処理の書き方は,このサイトを参考にしました.*numWorkersで並列数(Goではプロセスでもスレッドでもないらしいからなんと呼ぶか不明)を指定している.あと,WaitGroupをつかって全ての処理が終わるのを待っている.

  • メインの処理
func tex2Svg (wg *sync.WaitGroup, ch chan string) {
    defer wg.Done()
    for {
        texPath, isOpen := <-ch
        if !isOpen{
            return
        }
        texSource := loadTexSource(texPath)
        svgSource := fetchSvgSource(texSource)
        saveSvg(svgSource, texPath)
    }
}

非常にシンプル (だと思う).これもここを参考にしている.正直,Go初心者の僕には何をしているか分からない.特にdeferは謎.

  • texclipからsvgを取ってくるところ
// Global variables
var (
    UrlHead   = "https://texclip.marutank.net/render.php/_.svg?s="
    UrlFoot   = "&f=c&r=300&m=s&b=f&k=f"
)

func fetchSvgSource(texSource string) ([]byte) {
    var strQuery string
    strQuery = url.QueryEscape(texSource)

    payload, _ := http.Get(UrlHead+strQuery+UrlFoot)
    defer payload.Body.Close()    
    svgByteSource, _ := ioutil.ReadAll(payload.Body)
    return svgByteSource
}

ここを参考に書いた.基本的にtexclipのURLにパーセントエンコーディング (これが何かは不明) したtexのソースを書いてGetすればいい.多分UrlHeadUrlFootの部分を書き換えるともっと機能を追加できる.

ほんとに並列化できてるの?

このほとんどコピペで作者が何も理解していない並列処理であるが,本当にgoで早くなるのか一応調べた.クローンしたディレクトリ上で以下のコマンドで試せます.test/には[alphabet].tex (計26ファイル) が入っています.

$ time ./tex2fig -d test -w 1 test/*.tex
real    0m13.456s
user    0m0.117s
sys     0m0.061s

$ time ./tex2fig -d test -w 2 test/*.tex
real    0m7.415s
user    0m0.133s
sys     0m0.039s

$ time ./tex2fig -d test -w 4 test/*.tex
real    0m6.252s
user    0m0.162s
sys     0m0.021s

$ time ./tex2fig -d test -w 26 test/*.tex
real    0m6.078s
user    0m0.177s
sys     0m0.074s

一応速くなっていますね.ちなみに僕のPCのCPUは2 CoreのCeleron(R) N4000 CPU @ 1.10GHz.まぁ,うん.もっと高性能なCPUなら恩恵あるかも.Web経由だからそこがボトルネックになってるかもしれません.
ファイル数と並列数を同じにして時間を計測(time tex2fig -w n 1.tex ... n.texみたいにして実行)すると,ファイル数が1のときは大体$0.7\ \mathrm{[sec]}$かかり,1ファイル増える毎におよそ$0.2\ \mathrm{[sec]}$ずつ増加していきました.つまり,これを等差数列としてみると,26ファイルの処理にかかる時間は

t_{26}=0.7 + (26-1)\times 0.2= 5.9\ \mathrm{[sec]}

となり,実際に大体この通りに動いていることが確認できます.この1ファイルあたりの時間の増加が何によるものかはよくわかりません:stuck_out_tongue_winking_eye:

おわりに

Golangはioとかnetに便利な関数がいろいろあることをしれました.
いいね,コメントいただけると嬉しいです.

2
0
2

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
2
0