はじめに
先日Rails6で画像処理ライブラリを変更するissueをやりました。
具体的にはImageMagick
からlibvips
に移行しました。
そこで、これからlibvips
に移行したい人のために移行する方法を書いていきます。
それでは、やっていきましょう。
実際のプルリクエストです。参考にしてください
libvipsに移行する手順
先に全体像を書いておきます。
また、Rails6バージョンを想定していることに注意です。
- 設定ファイルの修正
- 既存の
ImageMagick
に対応しているコードを修正する - (必要なら)Dockerfile, CI設定ファイルの修正もする
libvipsに移行するだけなら、簡単なのですがアプリによって2の修正箇所が違ったりするので大変です。
以下で詳しく書いていきます
1. 設定ファイルの修正
config/application.rb
ファイルに1行加えるだけで、ライブラリ自体は変更できてしまいます。
# frozen_string_literal: true
...
module Myapp
class Application < Rails::Application
...
# 下記1行を追加する
config.active_storage.variant_processor = :vips
end
end
これだけです、簡単ですね。
ただ、ここから気をつけないとエラーを起こしてしまうので2は特に要チェックです。
2. 既存のImageMagick
に対応しているコードを修正する
ここから、既存のコードをlibvipsに対応させていきます。
主に見るのはvariant
メソッドについてです。
下記のように画像をvariant
で加工している箇所はないでしょうか?
avatar.variant(resize: '88x88>').processed.url
主にその箇所を修正していきます。
もっと具体的にいうとresize: '88x88>'
という部分を修正します。
Railsガイドに書いてある下記の表が、参考になります。
パラメータ 例 説明 resize_to_limit resize_to_limit: [100, 100] 元の縦横比を維持したまま、指定の寸法に収まるように画像を縮小します。指定の寸法より大きい場合のみ、画像のサイズを変更します。 resize_to_fit resize_to_fit: [100, 100] 元の縦横比を維持したまま、指定の寸法に収まるように画像をリサイズします。指定の寸法より大きい場合は縮小し、小さい場合は拡大します。 resize_to_fill resize_to_fill: [100, 100] 元のアスペクト比を維持したまま、指定の寸法に収まるように画像をリサイズします。必要な場合は、大きい方の寸法で画像を切り取ります。 resize_and_pad resize_and_pad: [100, 100] 元の縦横比を維持したまま、指定の寸法に収まるように画像をリサイズします。必要に応じて、元画像にアルファチャンネルがある場合は透明色で、ない場合は黒で残りの領域を塗ります。 crop crop: [20, 50, 300, 300] 画像から領域を抽出します。最初の2つの引数は、抽出する領域の左端と上端、最後の2つの引数は、抽出する領域の幅と高さです。 rotate rotate: 90 画像を指定の角度だけ回転します。
例えば、resize_to_limit
を使って先ほどの修正対象のコードを修正したら下記のようになります。
avatar.variant(resize_to_limit: [88, 88]).processed.url
厳密には違うかもですが、あくまでイメージですので許してください。
注意: ImageMagick依存のgemもチェックしよう
上記の修正を終えた僕は「なんだ〜〜簡単じゃん!!」と油断していました。
しかし、本番環境にリリースされた時バグを発生させてしまったのです。
(しかも、結構クリティカルなバグ...)
なぜバグが起こったのでしょうか?
それはMiniMagick
というgemを使って画像処理をしていた箇所でエラーを起こしていました。
どうやら、MiniMagick
を使うにはImageMagick
が必要だったそう...
なので、下記のようなコードを見つけたらlibvips
に対応した書き方に修正しましょう。
MiniMagick::Image.read()
結局チームリーダーが対処してくださいました↓
ありがとうございました。
(必要なら)Dockerfile, CI設定ファイルの修正もする
開発しているアプリにもよりますが、Dockerfile, CI設定のファイルでもlibvips
をインストールしないとエラーになります。
具体的には、下記のようなエラーになりました。
rails aborted!
LoadError: Could not open library 'vips.so.42': vips.so.42: cannot open shared object file: No such file or directory.
Could not open library 'libvips.so.42': libvips.so.42: cannot open shared object file: No such file or directory.
Searched in <system library path>, /usr/lib, /usr/local/lib, /opt/local/lib
/home/circleci/project/vendor/bundle/ruby/3.1.0/gems/ffi-1.16.3/lib/ffi/dynamic_library.rb:65:in `load_library'
/home/circleci/project/vendor/bundle/ruby/3.1.0/gems/ffi-1.16.3/lib/ffi/library.rb:95:in `block in ffi_lib'
/home/circleci/project/vendor/bundle/ruby/3.1.0/gems/ffi-1.16.3/lib/ffi/library.rb:94:in `map'
/home/circleci/project/vendor/bundle/ruby/3.1.0/gems/ffi-1.16.3/lib/ffi/library.rb:94:in `ffi_lib'
/home/circleci/project/vendor/bundle/ruby/3.1.0/gems/ruby-vips-2.2.0/lib/vips.rb:573:in `<module:Vips>'
...
libvips
を開けないよ!みたいなエラーなので、インストールしていきましょう。
ただ、設定ファイルは各自の開発しているアプリにより違いそうなので、カスタマイズしてください。
Dockerfileの修正
imagemagick
の部分をlibvips
をインストールするように置き換えています。
# Install OS packages
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# 修正前
&& apt-get -y install --no-install-recommends imagemagick pngcrush optipng gsfonts
# 修正後
&& apt-get -y install --no-install-recommends libvips42 libvips-dev pngcrush optipng gsfonts
# ImageMagick(修正前)
RUN apk add --no-cache imagemagick imagemagick-heic imagemagick-jpeg imagemagick-pdf imagemagick-svg imagemagick-webp bash pngcrush optipng=0.7.8-r0 ghostscript-fonts
# libvips(修正後)
RUN apk add --no-cache vips-dev orc-dev bash pngcrush optipng=0.7.8-r0 ghostscript-fonts
CI設定ファイル
こちらは単純にapt-get
でパッケージをインストールするだけになります。
...
# (すでに同様のcommandがあれば不要)パッケージの更新
- run:
name: Update package list
command: sudo apt-get update
# libvipsをインストールする
- run:
name: Install libvips
command: sudo apt-get install -y libvips
ひとまずこれでOKだと思います。
HEIC形式に注意する
上記の方法で、またもや本番エラーを起こしてしまいました。
HEIC形式に対応していなかったのです。
なので、先ほどのDockerfileを修正しましょう。
# vips-heifを追加する
RUN apk add --no-cache vips-dev vips-heif orc-dev bash pngcrush optipng=0.7.8-r0 ghostscript-fonts
こちらのリーダーに対処していただきました。何度もすいません...
また、こちらのコメントも参考になりました↓
(僕のインストール方法がそもそもでよくなかった?)
終わりに
以上で完了です!意外とスッといけたと思ったら本番でエラーばかりでした...
申し訳ございません。フォローありがとうございました
この記事を読んで少しでも事故が減ればいいなと思っています。
いいねなどもしていただけると嬉しいです
それでは!