まえがき
- GoでANSIエスケープシーケンスをパースしてテキストを着色して画像に起こすコマンドを作った
作った経緯
- screenfetchやcczeなどで着色されたテキストを画像に起こしたかった
- ImageMagickのconvertコマンドではANSIエスケープシーケンスでの着色を画像に起こせなかった
成果物
使い方
標準入力からANSIエスケープシーケンスと一緒にテキストを渡すと、画像を吐き出します。
端末上に垂れ流しても仕方ないので、ファイル出力か、パイプ先が存在しないときは出力しません。
$ seq 0 255 | while read -r i; do
echo -ne "\x1b[38;5;${i}m$(printf %03d $i)"
if [ $(((i+1) % 16)) -eq 0 ]; then
echo
fi
done | textimg -o 256_fg.png
アニメーションGIFも生成できます。
1フレームに何行のテキストを使うかも指定できます。
$ echo -e '\x1b[31mText\x1b[0m
\x1b[32mText\x1b[0m
\x1b[33mText\x1b[0m
\x1b[34mText\x1b[0m
\x1b[35mText\x1b[0m
\x1b[36mText\x1b[0m
\x1b[37mText\x1b[0m
\x1b[41mText\x1b[0m
\x1b[42mText\x1b[0m
\x1b[43mText\x1b[0m
\x1b[44mText\x1b[0m
\x1b[45mText\x1b[0m
\x1b[46mText\x1b[0m
\x1b[47mText\x1b[0m' | textimg -a -o ansi_fb_anime_1line.gif
絵文字も描画できるのですが、環境構築がちょっと面倒。詳細はREADME見てもらえれば。
$ echo Test👍 | textimg -o emoji.png
インストール
絵文字とかを描画できなくて良いのでしたら以下だけで十分です。
go get -u github.com/jiro4989/textimg
絵文字を描画したいなら絵文字のフォントや絵文字の画像を用意する必要があります。
用意する方法についてはREADMEに記載しているのでそちらを参照していただければ。
それらもろもろ含めたDockerイメージを用意しているのでそれを使うのもありです。
docker pull jiro4989/textimg
docker run -v $(pwd):/images -it jiro4989/textimg -h
docker run -v $(pwd):/images -it jiro4989/textimg Testあいうえお😄 -o /images/a.png
docker run -v $(pwd):/images -it jiro4989/textimg Testあいうえお😄 -s
実装
使用したライブラリ
- mattn/go-runewidth
- spf13/cobra
- x/image
ロジック
ANSIエスケープシーケンスを含むテキストを以下のように分解します。
パースは自力でガリガリやってます。汚いですが放置してます。
https://github.com/jiro4989/textimg/blob/master/escseq/parse.go#L67
分解した要素はそれぞれテキストか、ANSIエスケープシーケンスのどちらかです。
それぞれの要素が続く限り、以下のフローで処理します。
画像バッファにひたすらテキストを描画するわけですが、ANSIエスケープシーケンスのときは色の変数の更新だけで座標を更新せず、
テキストの時はANSIエスケープシーケンスを使用して画像を描画し、座標を更新するようなフローを延々続けるだけです。
https://github.com/jiro4989/textimg/blob/master/ioimage/image.go#L58
機能追加してる内に関数が肥大化して汚くなってどうしたものかな、と思ってるけれど、欲しかった機能を実装しつくしてやることがないので放置してます。
色のマッピング
愚直にRGB値とマッピングしてます。
https://github.com/jiro4989/textimg/blob/master/escseq/color.go#L79
まとめ
以下の内容について書きました。
- textimgの使い方
- textimgのインストール方法
- textimgの実装
最初はANSIエスケープシーケンスを画像に再現するだけだったのですが、
気がついたらアニメーションGIFを生成できるようになっていたり、
いつのまにか色々できるようになってました。
Goで実装するの楽しいですね。
以上です。