読者です 読者をやめる 読者になる 読者になる

Yamakichi’s blog

yamakichiの技術ブログ

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

開発 Ruby 思考の整理

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作った