はじめに
前回はRMagickを用いて画像のリサイズの仕方を紹介しました。今回は,RMagickでのアニメGIFの取り扱いについて説明していきます。
なお,紹介するすべてのサンプルコードは,事前に以下のコードを実行している前提で記述しています。また,破壊メソッドと非破壊メソッドの両方があるメソッドについては,サンプルコードでは特段の理由がない限り破壊メソッドを利用しています。
require 'rubygems'
require 'rmagick'
height = 160
width = 160
scale = 0.5
| 動作確認環境 | ruby 1.8.6 ImageMagick 6.5.6-8 rmagick 2.12.0 |
|---|
サンプル画像は以下を用います。
アニメGIFファイルの読み込み
RMagickでアニメGIFファイルの読み込みを行う場合は,以下のようにImageList.newメソッドを用いて行います。
なお,ImageListクラスは,大雑把な理解としてはアニメGIFを扱うためのクラスと考えていても間違いないと思います(もちろん他の画像形式で使うこともできますし,使うと便利なケースもありますが)。
ilist = Magick::ImageList.new('original.gif')
アニメGIFの構成
アニメGIF,特に画像が少しずつ変化していくアニメーションの場合には,各コマごとの画像を別々に持つのではなく,コマ間の差分をデータとして持つことがよくあります。
たとえば,サンプルの画像では次のような構成になっています。
ちなみに,コマ別の画像を得るためには,ImageListを使ってファイルを開き別ファイル形式で保存するのが簡単です。指定ファイル名にナンバリングしたファイルを自動的に作ってくれます。
ilist = Magick::ImageList.new('original.gif')
ilist.write('original.png')
アニメGIFのリサイズ
アニメGIFをリサイズする場合に気をつけなければいけない点がいくつかあります。サンプルとする画像によっては問題にならないケースもありますが,実際に,どんな問題が起こるのか,何をすべきかを紹介していきます。
普通にリサイズしてみる
前回紹介したresizeメソッドを使ってそのままリサイズしてみます。
ilist = Magick::ImageList.new('original.gif')
ilist.resize!(scale)
ilist.write('just_resize.gif')
すると,最後のコマだけがリサイズされてしまい残念な結果になってしまいました。これではいくらなんでも使いものにならないので,きちんとフレーム(コマ)毎にリサイズする必要があります。
図3 just_resize.gif

フレーム毎にリサイズする
次に,eachを回してフレーム毎にresize処理を呼び出してみます。
ilist = Magick::ImageList.new('original.gif')
ilist.each{|frame| frame.resize!(0.5)}
ilist.write('frame_resize.gif')
これで全フレームをリサイズすることはできましたが,できあがった結果を見るとやっぱり残念な感じになってしまっています。これは「アニメGIFの構成」のところで紹介したように,フレーム間を差分で持っているためです。これを補正するには一度差分から展開する必要があります。
図4 frame_resize.gif



