RailsでCarrierWaveを使い、画像をリサイズする方法です。OSはUbuntu Server 16.04です。
概要
リサイズにはImagemagickと、MiniMagickかRMagickが必要です。公式ではImagemagickとMiniMagickの組み合わせを推奨しているようです。この記事でもMiniMagickを使います。
Imagemagickのインストール
ImagemagickをUbuntuへインストールします。
$ sudo apt-get install imagemagick
convertコマンドが使えるようになっているので、バージョンを表示してみます。
$ convert -version Version: ImageMagick 6.7.7-10 2016-06-01 Q16 http://www.imagemagick.org Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC Features: OpenMP
MiniMagickのインストール
MiniMagickはgemをGemfileに追加します。
gem 'mini_magick'
$ bundle install
Vagrantを使っていて、実行時にNoMethodErrorとエラーが出る場合は、Vagrantを再起動すると直るかもしれません。
Uploaderの作成
rails generate uploaderでuploaderを作成します。CarrierWaveの設定ファイルみたいなものです。
rails generate uploader Image
#create app/uploaders/image_uploader.rb
生成されたapp/uploaders/image_uploader.rbを開いて、次のような感じにします。includeでMiniMagickを読み込みます。version :thumbでは、横幅300pxの画像を生成しています。
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :thumb do
process resize_to_fit: [300, nil]
end
end
Uploaderをマウントする
任意のモデルにstring型のカラムを用意して、Uploaderをマウントします。
例としてImageモデルにdataカラムを用意します。
create_table :images do |t| t.string :data # 画像データ(CarrierWave管理) end
モデル定義では次のようにマウントを指示します。
class Image < ApplicationRecord mount_uploader :data, ImageUploader end
使用する
リモートサーバーにある画像を取得し、CarrierWaveで保存してみます。
require 'mini_magick' begin uri = 'http://example.com/foo.jpg' img = MiniMagick::Image.open(uri) obj = Image.new obj.data = img obj.save! rescue => e p e end
public/uploads/imageフォルダにオリジナル画像とversion :thumbでリサイズした画像ができたかと思います。
オリジナル画像のサイズを変更する
オリジナル画像を縮小してから保存したい場合は、Uploaderにversion指定無しでprocessを指定します。
class ImageUploader < CarrierWave::Uploader::Base 略 # オリジナル画像を横幅600pxに制限して保存する。 process resize_to_fit: [600, nil] # 横幅300pxのバージョンも作成する。 version :thumb do process resize_to_fit: [300, nil] end end
オリジナル画像のサイズを変更すると画像が壊れる!?
上記のオリジナル画像に対してprocessを行ったときに、画像が壊れることがありました。下のように灰色の部分が生じました。
![]()
原因不明なので、Uploaderでオリジナル画像のリサイズを行わずに、MiniMagickでリサイズ済みの画像をCarrierWaveに渡すようにしました。
img.resize "600"の箇所がオリジナル画像のリサイズです。
require 'mini_magick' begin uri = 'http://example.com/foo.jpg' img = MiniMagick::Image.open(uri) img.resize "600" obj = Image.new obj.data = img obj.save! rescue => e p e end