Ruby Freaks Lounge

第27回 RMagickを用いた画像処理:アニメGIF

この記事を読むのに必要な時間:およそ 2 分

はじめに

前回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

サンプル画像は以下を用います。

図1 original.gif

※この画像はネムリクスリで配布されているものを使用させていただきました。

アニメGIFファイルの読み込み

RMagickでアニメGIFファイルの読み込みを行う場合は,以下のようにImageList.newメソッドを用いて行います。

なお,ImageListクラスは,大雑把な理解としてはアニメGIFを扱うためのクラスと考えていても間違いないと思います(もちろん他の画像形式で使うこともできますし,使うと便利なケースもありますが)⁠

ilist = Magick::ImageList.new('original.gif')

アニメGIFの構成

アニメGIF,特に画像が少しずつ変化していくアニメーションの場合には,各コマごとの画像を別々に持つのではなく,コマ間の差分をデータとして持つことがよくあります。

たとえば,サンプルの画像では次のような構成になっています。

図2 original-0.png~original-5.png

図2-0 original-0.png 図2-1 original-1.png 図2-2 original-2.png 図2-3 original-3.png 図2-4 original-4.png 図2-5 original-5.png

ちなみに,コマ別の画像を得るためには,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

著者プロフィール

二ッ森大介(ふたつもりだいすけ)

株式会社ドリコム所属。業務では主にrubyを用いて開発を行っている。
twitter: http://twitter.com/d2mr

「楽しさ」を作れる人探しています!
ソーシャルゲーム開発者・デザイナー募集中!
<ドリコム採用情報>

コメント

コメントの記入