回る長い猫のシェル芸とは?
コマンド
以下のコマンドで生成することができます。
$ eval "convert -delay 10 <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete `for i in {30..600..30};do echo -n "\( mpr:a -roll -$i+0 -wave 20x120 -distort arc 360 \) ";done`/images/x.gif"
前提条件
longcat と imagemagick がインストールされていること。
コマンドができるまで
長い猫を生成します。
$ longcat -n 10 -o /images/0.png
長い猫を標準出力(/dev/stdout)を通してimagemagick に入力して、少し整形します。
$ convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 /images/1.png
-flatten
で透過背景を白背景に変えて、-scale
でサイズを指定して、-rotate
で回転しています。
-wave
で波打たせます。
$ convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -wave 20x120 /images/2.png
$ convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -wave 20x120 -distort arc 360 /images/3.png
波打たせて丸める前の段階で、-roll -30+0
して、左側に30ピクセルずらしてやると、
$ convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -roll -30+0 -wave 20x120 -distort arc 360 /images/4.png
さきほどよりわずかに猫の頭が進んでいます。
さきほどは星型のへこんだところに猫が頭を突っ込んでいましたが、今は次の出っ張ってるところへ進んでいますね。
これを一周するまで繰り返します。
$ eval "convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete `for i in {30..600..30};do echo -n "\( mpr:a -roll -$i+0 -wave 20x120 -distort arc 360 \) ";done`/images/z.png"
evalすることで、for文が展開された後の文字列を評価しています。evalのかわりにechoしてみて、for文がどのように展開されているか見ておきましょう。
$ eval "convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete `for i in {30..600..30};do echo -n "\( mpr:a -roll -$i+0 -wave 20x120 -distort arc 360 \) ";done`/images/z.png"
convert <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete \( mpr:a -roll -30+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -60+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -90+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -120+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -150+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -180+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -210+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -240+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -270+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -300+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -330+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -360+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -390+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -420+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -450+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -480+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -510+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -540+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -570+0 -wave 20x120 -distort arc 360 \) \( mpr:a -roll -600+0 -wave 20x120 -distort arc 360 \) /images/z.png
波打たせて丸める前の状態で-write mpr:a
で mpr:a にイメージを格納して、+delete
でイメージシーケンスをクリアして、その後は mpr:a を-roll
して-wave
して``` -distort ``したものを20個、イメージシーケンスに並べています。最後に /images/z.png とすることで、/images/z-0.png から /images/z-19.png の連番ファイルに出力します。
アニメーションにします。
$ eval "convert -delay 10 <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete `for i in {30..600..30};do echo -n "\( mpr:a -roll -$i+0 -wave 20x120 -distort arc 360 \) ";done`/images/x.gif"
出力ファイルパスの拡張子をgifにすることで、イメージシーケンスの全イメージをgifアニメーションとして書き込みます。
完成。
-delay 10 はアニメーション1コマの時間指定です。高速回転にしてみましょう。
$ eval "convert -delay 3 <(longcat -n 10 -o /dev/stdout) -flatten -scale 150x600! -rotate -90 -write mpr:a +delete `for i in {30..600..30};do echo -n "\( mpr:a -roll -$i+0 -wave 20x120 -distort arc 360 \) ";done`/images/x.gif"
以上。