necotech blog

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
Share on Facebook
Share on LinkedIn
Pocket