LoginSignup
20
5

More than 3 years have passed since last update.

GoでANSIエスケープシーケンスで着色されたテキストを画像に起こすコマンドを作った

Posted at

まえがき

  • GoでANSIエスケープシーケンスをパースしてテキストを着色して画像に起こすコマンドを作った

作った経緯

  • screenfetchやcczeなどで着色されたテキストを画像に起こしたかった
  • ImageMagickのconvertコマンドではANSIエスケープシーケンスでの着色を画像に起こせなかった

成果物

GitHub - jiro4989/textimg

使い方

標準入力から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

image.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

ansi_fb_anime_1line.gif

絵文字も描画できるのですが、環境構築がちょっと面倒。詳細はREADME見てもらえれば。

$ echo Test👍 | textimg -o emoji.png

image.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エスケープシーケンスを含むテキストを以下のように分解します。

image.png

パースは自力でガリガリやってます。汚いですが放置してます。
https://github.com/jiro4989/textimg/blob/master/escseq/parse.go#L67

分解した要素はそれぞれテキストか、ANSIエスケープシーケンスのどちらかです。
それぞれの要素が続く限り、以下のフローで処理します。

image.png

画像バッファにひたすらテキストを描画するわけですが、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で実装するの楽しいですね。

以上です。

out.gif

20
5
0

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
20
5