yamarkz's blog

紫陽花

Rails, Carrierwave, MiniMagick, Piet, 画像アップロード, 画像圧縮

Railsで画像をアップロードし、かつ画像圧縮も行いたい時の実装をメモで残す。

環境

Macbook

OSX 10.11.6

Rails 5.0.0

Ruby 2.3

Carrierwave

Piet

MiniMagick

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を利用している。

png_quantizator

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を作ったので興味があればこちらも。

Rails CarrierWave アップロード画像を良い感じに圧縮するGem作った