JSで使うパラパラ漫画用の画像を作るのにImageMagickが便利すぎる
GIFじゃ力不足で、動画にするようなものでもないアニメーションが必要な時、JavaScriptを使ってパラパラ漫画のようにアニメーションさせるような手法がある。ただ、画像を毎フレーム切り替えるような方法だと、フレームの数だけサーバとやり取りする必要があるため、普通は1枚の画像にまとめてbackground-positionをずらす方法を取ることが多い。(要はCSSスプライト。)
で、アニメーション1つとかならいいんだけど、数十フレームのアニメーションが大量に必要になり、でもフレームごとに1枚画像になっていて、それらを全部くっつけていく作業を思うと途方にくれた…。なので、スクリプト組むかーとか思って調べたら、ImageMagickならどうやら一発でできるらしい!ということが分かった。
montageコマンド
・ImageMagick を使って画像を結合する方法
・行・列を指定して複数画像を結合する | ImageMagick コマンドリファレンス
上記をそのまま使うだけなのだけど、今回やった方法として補足。
-tileオプション
横並びとして、フレーム数をそのまま書けばいい。
30フレームなら、-tile 30×1 とする。
-geometryオプション
今回、これを指定せずにずれてしまってちょっとハマった。これも単純に1フレーム分の画像サイズを記述するだけ。
-geometry 150×150
フレームが多い場合
コマンドにミスがあると面倒臭いので、スクリプトでまとめて記述してしまおう。たとえば、Rubyだと以下みたいな感じに。
frames = 1.upto(30).map{|i| sprintf("%02d.png", i)}
system "montage #{frames.join(' ')} -tile #{frames.length}x1 -geometry 150x150 -background none out.png"
あとは、適当なルール通りに画像を配置した環境で上記スクリプトを回せばいい。ちなみに、今回使ったスクリプトを簡略化するとこんな感じ。
def conv(dir)
Dir.chdir dir
frames = 1.upto(30).map{|i| sprintf("%02d.png", i)}
system "montage #{frames.join(' ')} -tile 30x1 -geometry 150x150 -background none ../#{dir}.png"
Dir.chdir "../"
end
Dir["*"].each do |d|
conv d if File.directory? d
end