mini_magickとImageMagickで画像を切り取る

capybara-webkitで撮影した縦長のwebページスクリーンショット(PNG)を、1:1.41のA4縦長で印刷できるサイズ(JPEG)に分割する。

brew install imagemagick
gem install mini_magick

mini_magick版

#!/usr/bin/env ruby
require 'rubygems'
require 'mini_magick'

source = ARGV.shift
img = MiniMagick::Image.open source

puts "#{img[:width]}x#{img[:height]}"
w = img[:width]
h = (w*1.41).to_i

0.upto(img[:height]/h) do |i|
  puts fname = "#{i}.jpg"
  img = MiniMagick::Image.open source
  img.format('jpg')
  img.quality('95')
  img.crop("#{w}x#{h}+0+#{i*h}")
  img.write(fname)
end

結果

1236x8026
0.jpg
1.jpg
2.jpg
3.jpg
4.jpg
ruby crop.rb ../capybara-screenshot/shokai.png  7.73s user 1.82s system 89% cpu 10.663 total

7.73秒かかった。
ImageMagickはファイルにあわせて画像フォーマットを決めてくれるのに、mini_magickではformatメソッドで指定しないと元画像のままPNG形式で保存されてしまっていた。
exiftoolで確認すべき。


ImageMagick

#!/usr/bin/env ruby
img = ARGV.shift

width, height = `identify '#{img}'`.split(/\s/).select{|i|
  i =~ /^\d+x\d+$/
}.first.split('x').map{|i| i.to_i}

puts "#{width}x#{height}"
w = width
h = (w*1.41).to_i

0.upto(height/h) do |i|
  puts fname = "#{i}.jpg"
  puts cmd = "convert -quality 95 -crop #{w}x#{h}+0+#{h*i} #{img} #{fname}"
  system cmd
end

結果

0.jpg
convert -crop 1236x1742+0+0 ../capybara-screenshot/shokai.png 0.jpg
1.jpg
convert -crop 1236x1742+0+1742 ../capybara-screenshot/shokai.png 1.jpg
2.jpg
convert -crop 1236x1742+0+3484 ../capybara-screenshot/shokai.png 2.jpg
3.jpg
convert -crop 1236x1742+0+5226 ../capybara-screenshot/shokai.png 3.jpg
4.jpg
convert -crop 1236x1742+0+6968 ../capybara-screenshot/shokai.png 4.jpg
ruby crop_imagemagick.rb ../capybara-screenshot/shokai.png  1.97s user 0.52s system 74% cpu 3.089 total

1.97秒だった。
ImageMagickを直に使ったほうが圧倒的に速い。

感想

  • ImageMagickを直に使ったほうが速い。しかし・・
  • 画像のサイズやフォーマットなどを読み取る場合、identifyコマンドを使うのだが文字列で返ってくるのでparseが面倒。mini_magickやrmagickを使ったほうが楽。
  • 画像のサイズを変えたり、色調を補正するぐらいならImageMagickをそのまま使ったほうが楽だし、高速。
    • 特に細かいオプションを設定したりする場合、それをラッパーから指定する方法を調べるのがめんどい。
  • 複数の画像を重ねあわせたりするならmini_magickなどを使ったほうが書きやすい。

使い分け

ちょっと画像を加工→ImageMagickを直に使う
画像のプロパティを読み取り、細かくに加工(というか装飾)→mini_magick
がいいのでは。