マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

LaTeXでつくる「回転ゆきだるまGIF画像」

今年は世界を襲った未曾有の疫病のため日常が……(中略)…………ゆきだるま☃!

LaTeXでつくる「ツイッタァーの進捗」

毎年恒例の「ゆきだるま☃の日」ですが、その日が近づくとツイッタァーに現れる「進捗を促す某ZR氏のツイート」もすっかりお馴染みのものとなりました(多分)。

くるくる回るゆきだるま☃をツイッタァーに上げるべき、というのは至極当然の提案ですね(多分)。

しかし、この提案に沿って、ツイッタァーに素敵な回転ゆきだるま☃のGIFアニメ画像を投稿しようとすると、すぐにある問題に気づくことでしょう。

回転ゆきだるま☃のGIFアニメ画像をどうやって作るか。

もちろん、回転ゆきだるま☃の画像をつくるツールや手法について何か指定があるわけではないので、GIFアニメ画像をつくるツールであれば何でも事足りるのは確かです。しかし、当ブログの読者の多くがLaTeXユーザであると思しきことを考えると、scsnowmanパッケージのカワイイゆきだるま☃を使ったLaTeXソースから回転ゆきだるま☃のGIFアニメ画像をつくることができたら最高に幸せであることは間違いないでしょう。

というわけで、今年の「ゆきだるま☃の日」の記事では、回転ゆきだるま☃画像をつくるスクリプトであるtcspingifを紹介します。

復習:LaTeXでつくる「回転☃文書」

LaTeXでゆきだるま☃を出力する方法は皆さんご存じでしょう。scsnowmanパッケージを利用すると、好きな色のマフラーや帽子を付けたゆきだるま☃を出力できます。

[sample-1.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\begin{document}
% 赤マフラーの素敵なゆきだるま☺
\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]%
\end{document}

f:id:zrbabbler:20200808205518p:plain
sample-1の出力(非回転)
あるいは、「自分は『原ノ味フォント』の☃が好きだ」という人なら、XeLaTeX(やLuaLaTeX)1でfontspecパッケージを利用した上で、大きなフォントサイズで「☃」の文字を書けばよいでしょう。

[sample-2.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=10pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\begin{document}
\fontsize{240}{0}\selectfont % サイズは240pt
\color{blue!60!black}%% ←素敵☺
\end{document}

f:id:zrbabbler:20200808205616p:plain
sample-2の出力(非回転)
これらの文書の出力は素敵ですが、しかし、回っていません。ゆきだるま☃を回転させるにはどうすればよいでしょうか。「LaTeXで何かを回転させる」ということなので、tcfaspinパッケージが使えそうです。

早速、ゆきだるま☃に\faSpin命令を適用してみましょう。

\faSpinを使用する場合、コンパイルを2回以上行う必要があります。

[sample-3.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
% \scsnowman を回転させる
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
[sample-4.tex]
% XeLaTeX文書; UTF-8
\documentclass[margin=25pt]{standalone}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% ←回転!
\end{document}

これをAdobe Readerで開くと……。

f:id:zrbabbler:20200808205648g:plain
sample-3の出力(回転!)
f:id:zrbabbler:20200808205725g:plain
sample-4の出力(回転!)

ゆきだるま☃が回りました! 素敵ですね! というわけで、あとはツイッタァーに投稿するだけ……アッ、チョット待って。この回転ゆきだるま☃は確かに回っていますが、GIF画像ではなくてPDF文書なので、残念ながらこのままではツイッタァーに投稿できません。どうにかして、このPDF文書を画像ファイルに変換しないといけません。

LaTeXでつくる「回転☃画像」

回転☃をImageMagickできない話

PDF文書を画像ファイルに変換する方法としては、(特にTeX界隈では)ImageMagickがよく使われます。例えば、最初の例のsample-1.pdfをPNG画像に変換するには、magickコマンド2を使って次のようにします。

ImageMagickでPDFファイルを扱うにはGhostscriptを併せてインストールする必要があります。

# sample-1.pdf を sample-1.png に変換する(-density はDPI値指定)
> magick -density 72 sample-1.pdf sample-1.png

ImageMagick自体はアニメGIF画像にも対応していますが、残念ながら、tcfaspinを利用した「回るPDF文書」を直接「回るGIF画像」に変換することはできません。これはtcfaspinがかなり特殊な処理を行っているからです3。従って、tcfaspinを使ったLaTeXソースから「ツイッタァーに上げるための回転ゆきだるま☃画像」を生成することは困難です。

回転☃をImageMagickする話

このままでは「ツイッタァー上の回転ゆきだるま☃画像がいつまで経っても増えない」という由々しき事態になりかねません。この困難を打破するため、スクリプトつくりました

このPerlスクリプト tcspingif.pl の実行には以下のインストールが必要です。

tcspingif.pl を使うとコマンド1つで「tcfaspinを使ったLaTeX文書をアニメGIF画像に変換する」ことができます。例えば、先の例にあるsample-3.texとsample-4.texの場合、次のコマンドを実行することで、「PDF文書と同じ出力(同じ動き)」のGIF画像が得られます。

# pdfLaTeX文書 sample-3.tex をGIF画像 sample-3.gif に変換する
> perl tcspingif.pl -e pdflatex sample-3.tex
# XeLaTeX文書 sample-4.tex をGIF画像 sample-4.gif に変換する
> perl tcspingif.pl -e xelatex sample-4.tex

オプションは次の通りです(詳しくは--help付実行で出るヘルプを参照)。

  • -e <名前>: 使用するLaTeXのエンジン(コマンド名、例えばxelatex)。(既定値=pdflatex
    ※DVI出力のエンジン(platexなど)を指定した場合、PDFに変換するのにdvipdfmxが使われます。
  • -d <実数>: 出力解像度のDPI値。(既定値=72
  • -t <整数>: 1回転中のフレーム数。既定値はtcfaspinのオプションで指定された値で、さらにその既定値は32。
  • -b <実数>: 回転速度の標準に対する倍率。(既定値=1
    ※標準は「2秒で1回転」です4。ただし、アニメGIFのフレーム時間設定が10ミリ秒単位であるため実際には誤差が出ます。

チョット補足

生成される画像の大きさは元のPDF文書のものを引き継ぐので、大きさを調整したい場合は、standaloneクラスを利用した上で

  • standaloneのmarginオプションで適宜調節する
  • 文書本体を1つのpicture環境(の類、例えばTikZのtikzpicture環境)にしてその外形を所望のサイズに設定する

などの工夫をすればいいでしょう。

※以下、解像度指定(-dオプション)は72dpiとします。この場合、LaTeX内の1bpが1ピクセルに対応することになります。

例えば、sample-3.texではmarginの値は25ptとなっていますが、これを0ptに変えると出力の大きさは縦横309ピクセルとなります(そして回転の途中で一部が外にはみ出す)。これを縦横360ピクセルで出力するには、marginを25.5bpに指定すればよいことになります((360-309)÷2=25.5)。

[sample-5.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage[svgnames]{xcolor}
\usepackage{scsnowman}% ゆきだるま☃!
\usepackage{tcfaspin}% 回転!
\begin{document}
\faSpin{\scsnowman[scale=40,
  muffler=Red,hat=Green,buttons=RoyalBlue,
  arms=Brown,snow=SkyBlue]}%
\end{document}
# sample-5.tex をGIF画像 sample-5.gif に変換する
> perl tcspingif.pl -e pdflatex sample-5.tex

f:id:zrbabbler:20200808205648g:plain
sample-5の出力(回転GIF!)

同様に、sample-4.texを縦横280ピクセルで出力する場合は、以下のように調整することになります5

[sample-6.tex]
% XeLaTeX文書; UTF-8
\documentclass{standalone}
\standaloneconfig{margin={20.5bp 26bp}}
\usepackage{xcolor,fontspec}
\setmainfont{Harano Aji Mincho}% 原ノ味明朝
\usepackage{tcfaspin}
\begin{document}
\fontsize{240}{0}\selectfont
\color{blue!60!black}%
\faSpin{}% 回転!
\end{document}
# sample-6.tex をGIF画像 sample-6.gif に変換する
> perl tcspingif.pl -e xelatex sample-6.tex

f:id:zrbabbler:20200808205725g:plain
sample-6の出力(回転GIF!)

tcspingif.plを使うことで、素敵な「回転ゆきだるま☃」の画像をつくることができました!

おまけ:「点滅☃画像」する話

実は、tcspingif.plはtcfaspinパッケージの他にbxblinkパッケージにも対応しています6。つまり、tcspingif.plを利用すると、「回転ゆきだるま☃」だけでなく「点滅ゆきだるま☃」の画像も生成できます(素敵)。

[sample-7.tex]
% pdfLaTeX文書; UTF-8
\documentclass[margin=25.5bp]{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}% 点滅!
\begin{document}
\textblink{\scsnowman[scale=40,
  muffler=red,hat=red!75!black,buttons,arms,snow]}%
\end{document}
# sample-7.tex をGIF画像 sample-7.gif に変換する
> perl tcspingif.pl -e pdflatex sample-7.tex

f:id:zrbabbler:20200808222213g:plain
sample-7の出力(点滅GIF!)

イロイロやってみる

某ZR氏のツイッタァーでよく見かけるやつ

「赤マフラーと青マフラーと緑マフラーのやつが並んで回っている」画像をつくってみましょう。基本的なデザインを次のように決めます:

  • 画像のサイズを600×240ピクセルとする。
  • 横に三等分した領域の真ん中にゆきだるま☃を配置する。つまり、(100,120)に赤マフラー、(300,120)に青マフラー、(500,120)に緑マフラーを置く。

描画にはTikZを利用しますが、ここで座標の単位をピクセル(既に述べた通り、これは1bpと同じです)に合わせるために、tikzpicture環境の設定にx=1bp,y=1bpを入れておきます。また、最初のうちはtcfaspinを読み込まずに、「PDFファイルの更新に表示を追随する」機能をもつPDFビューアを用いてゆきだるま☃の位置や大きさを調整するのがよいでしょう。

% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\colorlet{mygreen}{green!50!black}
%\usepackage{tcfaspin}% まだ読み込まない
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]% 座標を"ピクセル"単位にする
% 画像全体のサイズを600×240ピクセルに設定する
\useasboundingbox (0,0) rectangle (600,240);
% ↓満足するまで試行錯誤して調整する
\node at (100,120) {% 赤マフラー
  \scsnowman[muffler=red,scale=XXX,...]};
\node at (300,120) {% 青マフラー
  \scsnowman[muffler=blue,scale=XXX,...]};
\node at (500,120) {% 緑マフラー
  \scsnowman[muffler=mygreen,scale=XXX,...]};
\end{tikzpicture}
\end{document}

満足する構成が得られたら、tcfaspinを読み込んだ上で、\scsnowmanの出力に\faSpinを適用します。

[sample-8.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}
\colorlet{mygreen}{green!50!black}
\colorlet{mylbrown}{rgb,10:red,7;green,5}
\pagecolor{mygreen!5}
\usepackage{tcfaspin}% 回転!
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (600,240);
\node at (100,120) {% 赤マフラー(ほうき)
  \faSpin{\scsnowman[scale=15,
    hat=red!75!black,muffler=red,
    broom=mylbrown,snow,arms,buttons]}};
\node at (300,120) {% 青マフラー(冷や汗)
  \faSpin{\scsnowman[scale=15,
    hat=blue!75!black,muffler=blue,
    arms,buttons,sweat,mouthshape=tight]}};
\node at (500,120) {% 緑マフラー(♪)
  \faSpin{\scsnowman[scale=15,
    hat=mygreen!75!black,muffler=mygreen,
    note=green!30!black,snow,arms,buttons]}};
\end{tikzpicture}
\end{document}

まずは普通にpdflatexでPDFに変換してAdobe Readerで回転している様子を確かめます。イイカンジだったら、いよいよtcspingifを実行して画像に変換しましょう。

# sample-8.tex をGIF画像 sample-8.gif に変換する
> perl tcspingif.pl -e pdflatex sample-8.tex

f:id:zrbabbler:20200809004753g:plain
sample-8の出力(0.5Hzくらい)

これでもイイカンジですが、某ZR氏によると、ゆきだるま☃の回転速度は「1Hzあたり(1秒で1回転)」がよいらしいです。なので、速度を2倍に上げましょう。

# 回転速度を2倍にする
> perl tcspingif.pl -e pdflatex -b 2 sample-8.tex

f:id:zrbabbler:20200809004831g:plain
sample-8の出力(1Hzくらい)

トッテモ素敵!

どっかのSlackでよく見かけるやつ

「雪だけ点滅しているやつ」の画像をつくってみましょう。次のようにします:

  • 雪つきの\scsnowmanを描いて、それを点滅させる。
  • その後に、全く同じ位置に、雪なしの\scsnowmanを描く。結果的に雪の部分だけ点滅しているように見える。
[sample-9.tex]
% pdfLaTeX文書; UTF-8
\documentclass{standalone}
\usepackage{xcolor,scsnowman}% ゆきだるま☃!
\usepackage{bxblink}
\begin{document}
\begin{tikzpicture}[x=1bp,y=1bp]
\useasboundingbox (0,0) rectangle (360,360);
\node at (180,180) {% 雪つき, 点滅
  \textblink{\strut\scsnowman[scale=40,snow]}};
\node at (180,180) {% 雪なし
  \strut\scsnowman[scale=40,
    muffler=red,hat=red!75!black,buttons,arms]};
\end{tikzpicture}
\end{document}
# sample-9.tex をGIF画像 sample-9.gif に変換する
> perl tcspingif.pl -e pdflatex sample-9.tex

f:id:zrbabbler:20200809004908g:plain
sample-9の出力(素敵!)

やっぱり素敵!

まとめ

というわけで、「せっかくのお盆休みなのに外出自粛のせいで何もやることがない」という人は、自作の「回転ゆきだるま☃画像」を一日中眺めて本質的な「おうち時間」を楽しみましょう! 時には「点滅ゆきだるま☃」もよいかもしれません!


  1. このように「文字を画像として使う」あるいは「画像に文字を入れる」という場合は「和文組版用の調整」は不要(あるいは却って邪魔)であることが多く、その場合、LaTeXエンジンの選択として(u)pLaTeXは避けるのが無難です。日本語処理パッケージを併用せずにpdfLaTeX・XeLaTeX・LuaLaTeXを使用しましょう。OpenTypeフォントを使う場合は、処理時間の点でLuaLaTeXよりもXeLaTeXの方がオススメです。

  2. ImageMagickの古い版では変換用のコマンドはconvertという名前でした。

  3. tcfaspinは内部でanimateパッケージを利用しています。そして、animateパッケージはPDFのスクリプティング機能を利用してページ上のオブジェクトを動的に変化させています。

  4. tcfaspinの\faSpin命令は元来はWebのfontawesomeのfa-spinクラス指定の動作を模倣するものなので、その回転速度に合わせています。

  5. marginの値を縦と横で変えるにはmargin={<横> <縦>}という形で設定しますが、このように{ }を含む指定はクラスオプションでは受け付けられないので、代わりに\standaloneconfigという命令で設定する必要があります。

  6. bxblinkを使用した文書の場合、tcspingifの-tオプションの既定値は8になります。