CarrierWave + RMagick 画像のリサイズをまとめてみました

こんにちは。麺処まつば副店長です。
久々の投稿ですけど、もう色々気にしないことにしました。
店長の視線がなんだって言うんですか。(キッ)

さて副店長、先日中ずっとCarrierWaveを扱っておりまして
その中でRMagickを使った画像のリサイズもやっておりました。
このリサイズ用のメソッドがいくつか存在するのですが
http://rubydoc.info/gems/carrierwave/CarrierWave/RMagick
副店長は鳥頭のため…、何度やっても「どれがどうなるんだっけ?」という状況に…。
そこで、リサイズメソッドと実行の結果を何パターンかまとめてみます。

まずはオリジナルのこのような画像を用意してみました。
↓100×100(各マス20x20)の画像です。
(なぜか5段目の青だけ濃ゆいのですが、どうかお気になさらず…。)
f:id:noodles_mtb:20130708123634p:plain

では、この画像を下記のメソッドにかけてみます。
・resize_to_fit
・resize_to_limit
・resize_and_pad
・resize_to_fill

resize_to_fit(width, height)

まずはお馴染みの resize_to_fit です。
縦横比を保持したまま、指定されたサイズに収まるようリサイズします。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708135235p:plain  
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708123634p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708123634p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708123634p:plain  
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  

resize_to_geometry_string(geometry_string)

引数に与えられた文字列から、リサイズを行います。

  resize_to_geometry_string("150x50")

このような形で150x50でリサイズします。
実行したときの挙動はおそらく resize_to_fit のそれと同じです。
違っていたらどなたかツッコミお願いします。

resize_to_limit(width, height)

resize_to_fitと同様に縦横比を維持したままリサイズします。
resize_to_fitとの違いは、対象の画像のサイズが引数に指定された縦横サイズ以内の場合はリサイズしません。
指定された縦横サイズをオーバーした場合にのみ、指定されたサイズに収まるようリサイズします。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708125306p:plain resize_to_fitと違うところ。
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708125306p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708125306p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708125307p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708130121p:plain  

resize_and_pad(width, height, background = :transparent, gravity = ::Magick::CenterGravity)

与えられたwidthとheightで resize_to_fit のリサイズをします。
さらに足りない部分にbackgroundの色を敷きます(副店長は座布団と呼んでいます。)
座布団を敷くので、必ず指定されたサイズぴったりの画像になります。
gravityは座布団の上のどの位置に画像を配置するか、です。
下記の例では、黒い座布団の中央にリサイズした画像を配置するようにしています。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708142755p:plain 所々黒いのは元画像が透過のため
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708142942p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143058p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143209p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708143255p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143342p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143430p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143525p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708143606p:plain  

resize_to_fill(width, height, gravity = ::Magick::CenterGravity)

縦横比固定でリサイズをして、さらにgravityで指定された位置をくりぬきます。
指定された width と height のサイズでくり抜ける所まで引き伸ばして、くりぬくイメージ。

指定サイズ 元画像 実行後の画像 備考
150x150 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708144240p:plain  
150x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144331p:plain  
150x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144550p:plain  
100x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144639p:plain
100x100 f:id:noodles_mtb:20130708123634p:plain f:id:noodles_mtb:20130708123634p:plain
100x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144729p:plain  
50x150 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708144815p:plain  
50x100 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708145018p:plain  
50x50 f:id:noodles_mtb:20130708125307p:plain f:id:noodles_mtb:20130708145117p:plain  

オマケ:manipulate!(options = {}, &block)

上記にないリサイズ・加工をする場合は manipulate! を使う必要があります。
このような感じで。

class MenuPhotoUploader < CarrierWave::Uploader::Base 
  include CarrierWave::RMagick
  MAX_WIDTH = MAX_HEIGHT = 300
  
  process :set_bgcolor
  
  def set_bgcolor
    manipulate! do |img|
      img.background_color = 'whitesmoke'
      img.extent(MAX_WIDTH, MAX_HEIGHT, -(MAX_WIDTH-img.columns)/2, -(MAX_HEIGHT-img.rows)/2)
    end
  end # end set_bgcolor

end