Ruby/GD2でGIFアニメ

用事があってGIFのフォーマットだとかGIFアニメのことだとかを調べている。特許の話とかでてきて懐かしい。

GIFアニメについてはlibgd2の2.0.29で対応したようだ。が、言語バインディングではまだあまり対応していない様子。まだ、というか、libgd2の言語バインディングはあまりアクティブでないような感じもある。Ruby/GDもそんななかの一つ。今からコードを足すのもどうかなというところ。

そう思っていたらRuby/GD2という別の実装があることに気付いた。こちらもアクティブではないようだが、Ruby/DLで書かれているためちょっとだけ手を入れやすい。そういうわけで、関数をいくつか足し、Rubyレベルでのメソッドを三つほど足してGIFアニメを出力できるようにしてみた。

require 'gd2'
 
files = Dir.glob('/path/to/images/*.png')
 
prev = nil
open('/path/to/output.gif', 'w') do |io|
  img = nil
  files.each do |f|
    img = GD2::Image.import(f, :format => :png)
    img.gifanim_begin(io) if prev.nil?
    img.gifanim_add(io, 50, prev, true)
    prev = img
  end
  img.gifanim_end(io)
end

使っているlibgd2は2.0.36-RC1なのだけど、このバージョンのGIFアニメ機能にはバグがあるようだ。libgd2では、GIFアニメを構成するイメージの間での変更部分を抽出しようとするのだが、サイズが異なるイメージが与えられると、その処理の中でSEGVを起こす。ソース中のコメントには内部で調整するというようなことになっているのに、実際にはそういうことをやっているところがない。そのため、前述したメソッドでは前フレームのサイズに変換してしまうことにした。ま、そろえておけよっていうことではあるのだろうと思うのだけど。

追記: 差分にリンクしていたのだが、いつの間にかその差分を削除してしまっていたのに気付いた。いまさらだがweyback machineにあったのでリンクしておく。