Ruby で画像処理を行うには RMagick を利用するのが良いらしい。画像処理のためのソフトである ImageMagick を Ruby で操作するためのもののようだ。
RMagick のインストール
$ sudo apt-get install imagemagick libmagickwand-dev
$ gem install rmagick
$ irb
irb(main):001:0> require 'RMagick'
=> true
これでインストールは OK
RMagick を使ってみる
適当に動かしてみる。
画像の読み込みと保存
irb(main):002:0> require 'RMagick'
=> true
irb(main):003:0> image = Magick::Image.read('z3.png')
=> [z3.png PNG 804x477 804x477+0+0 DirectClass 8-bit 862kb]
irb(main):004:0> image = Magick::Image.read('z3.png').first
=> z3.png PNG 804x477 804x477+0+0 DirectClass 8-bit 862kb
Magick::Image.read メソッドは Array を返すので最初の要素を .first で取得している。[ ] で囲われているのがわかる。
バイナリから Image を作成するには以下のように from_blob を使用する。
# irb じゃなくて実際に利用しているコードから抜粋。
require 'cgi'
require 'RMagick'
cgi = CGI.new("html3")
imagedata = cgi.params['imagedata'][0].read
image = Magick::Image.from_blob(imagedata).first
write メソッドを利用する事で画像を保存できる。
irb(main):008:0> image.write('newfile.png')
=> z3.png=>newfile.png PNG 804x477 804x477+0+0 DirectClass 8-bit 600kb
画像フォーマットの変換
画像フォーマットを変換する時は、write でファイル名を渡す際に拡張子を変えてやるだけで勝手に変換してくれる。
irb(main):009:0> image.write('newfile.jpeg')
=> z3.png=>newfile.jpeg PNG 804x477 804x477+0+0 DirectClass 8-bit 128kb
irb(main):010:0> image.write('newfile.gif')
=> z3.png=>newfile.gif PNG 804x477 804x477+0+0 PseudoClass 256c 8-bit 280kb
PNG と出てくるので不安になるが od コマンドで確認してみるとちゃんと変換されているようだ。
$ od -tx1c z3.png | head -n 2
0000000 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52
211 P N G \r \n 032 \n \0 \0 \0 \r I H D R
$ od -tx1c newfile.jpeg | head -n 2
0000000 ff d8 ff e0 00 10 4a 46 49 46 00 01 01 02 00 26
377 330 377 340 \0 020 J F I F \0 001 001 002 \0 &
$ od -tx1c newfile.gif | head -n 2
0000000 47 49 46 38 39 61 24 03 dd 01 f7 00 00 02 03 02
G I F 8 9 a $ 003 335 001 367 \0 \0 002 003 002
画像の拡大縮小
RMagick で拡大縮小を行うメソッドは複数ある。
第26回 RMagickを用いた画像処理(1)リサイズ:Ruby Freaks Lounge|gihyo.jp … 技術評論社簡単にまとめてみる。
resize | 画質は良いがファイルサイズは大きくなる |
---|---|
scale | 画質は悪く、ファイルサイズも小さくなる |
thumbnail | ファイルサイズは大きくなるが実行速度は速い |
sample | 実行速度は早くサイズも小さいが中間色を作らないので画質は悪い |
どのメソッドも float を引数に取るので以下のように書ける。
irb(main):003:0> image.resize(0.1)
=> z3.png PNG 804x477=>80x48 80x48+0+0 DirectClass 8-bit
irb(main):004:0> image.scale(0.1)
=> z3.png PNG 804x477=>80x48 80x48+0+0 DirectClass 8-bit
irb(main):005:0> image.sample(0.1)
=> z3.png PNG 804x477=>80x48 80x48+0+0 DirectClass 8-bit
irb(main):006:0> image.thumbnail(0.1)
=> z3.png PNG 804x477=>80x48 DirectClass 8-bit
irb(main):007:0> image.resize!(0.1)
=> z3.png PNG 804x477=>80x48 80x48+0+0 DirectClass 8-bit
irb(main):008:0> image.resize!(0.1)
=> z3.png PNG 804x477=>8x5 8x5+0+0 DirectClass 8-bit
! をつけると破壊的メソッドとなるらしい。オブジェクトの中身を変更してしまうようだ。上記例だと最後の resize 二回だが実行する都度画像がどんどん小さくなっていってるのが分かる。
pixel 指定で画像のサイズを変更する際は resize_to_fit メソッドを利用すると良い。
irb(main):010:0> image.resize_to_fit!(80,48)
=> z3.png PNG 804x477=>80x47 80x47+0+0 DirectClass 8-bit
画像の一部を切り取る
画像の一部を切り取るには crop メソッドを利用する。以下のように3種類引数の渡し方がある。
img.crop(x, y, width, height) -> image
img.crop(gravity, x, y, width, height) -> image
img.crop(gravity, width, height) -> image
RMagick 2.12.0: class Image (class methods and instance methods a-d):
irb(main):014:0> image.crop(500,50,300,350).write("croped.png")
=> z3.png=>croped.png PNG 804x477=>300x350 804x477+500+50 DirectClass 8-bit 188kb
# 左上から500px,50px の地点より 300x350 の画像を生成
irb(main):019:0> image.crop(Magick::CenterGravity, 400, 300).write("cropped.png")
=> z3.png=>cropped.png PNG 804x477=>400x300 804x477+202+88 DirectClass 8-bit 212kb
# 中央基点にして 400x300 の画像を生成
簡単に扱えて便利だ。