Rails, Carrierwave, MiniMagick, Piet, 画像アップロード, 画像圧縮
Railsで画像をアップロードし、かつ画像圧縮も行いたい時の実装をメモで残す。
環境
OSX 10.11.6
Rails 5.0.0
Ruby 2.3
Gem
実装に必要なGemをインストール
gem "carrierwave" gem "piet" gem "mini_magick"
bundle install --path vendor/bundle
Piet
Carrierwaveのextensionとして画像圧縮を行えるようにするGem
圧縮を行う類似のGemがいくつか存在するがPietを採用
トータルダウンロード数 比較
piet : 242,713 carrierwave-imageoptimizer : 97,947
jpegoptim
.jpeg画像の圧縮で使用するパッケージ
brew install jpegiotim
pngquant
.png画像の圧縮で使用するパッケージ
画像圧縮を行うPietではpngquantを用いて圧縮を行えるように他のGemを利用している。
Pietのドキュメントに導入方法が記載
pngquantが圧縮効率が良いのでこちらを採用する。
圧縮効率の比較資料
brew install pngquant
アップローダーの作成
bundle exec rails g uploader image #=> app/uploaders/image_uploader.rb
上記のコマンドを実行しアップローダーを作成します。
class ImageUploader < CarrierWave::Uploader::Base include CarrierWave::MiniMagick include Piet::CarrierWaveExtension process quality: 80 # Large size process resize_to_limit: [640, 640] process :custom_optimize # Midium size version :midium do process resize_to_limit: [300, 300] process :custom_optimize end # Small size version :small do process resize_to_limit: [200, 200] process :custom_optimize end def extension_white_list %w(jpg jpeg gif png) end def mimetype IO.popen(["file", "--brief", "--mime-type", path], in: :close, err: :close) { |io| io.read.chomp.sub(/image\//, "") } end def custom_optimize case mimetype when "png" then pngquant when "jpeg", "gif" then optimize(quality: 90) end end
custom_optimize メソッド独自で定義し、画像の拡張子によって実行する圧縮を分岐させるような形に。
initialize以下のcarrierwave.rbにも定義
CarrierWave.configure do |config| # hogehoge end
module CarrierWave module MiniMagick def quality(percentage) manipulate! do |img| img.quality(percentage.to_s) img = yield(img) if block_given? img end end end end
流れで画像圧縮のGemを作ったので興味があればこちらも。