Railsで画像処理したいときはMiniMagickが使えます。MiniMagickはImageMagickのラッパーです。
リファレンスはhttps://github.com/minimagick/minimagickです。
準備 – ImageMagick
ImageMagickのインストールが必要です。
OS Xなら
$ brew install imagemagick
Ubuntuなら
$ sudo apt-get install imagemagick
終わったらバージョンを確認してみます。
$ 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のインストールはGemfileにgemを追加してインストールします。
gem 'mini_magick'
$ bundle install
使うときはrequire
します。
require 'mini_magick'
画像を開く
MiniMagickでファイルを開くには、MiniMagick::Image.open
を使います。こんな感じです。
image = MiniMagick::Image.open('画像ファイルへのパス')
リモートサーバー上の画像をURL経由で開く場合もopen
を使います。
image = MiniMagick::Image.open('画像へのURL')
画像データを直接流し込むにはMiniMagick::
Image.read
を使います。
image = MiniMagick::Image.read(画像データ)
画像がないと始まらないので、Railsアプリケーションのルートに画像を置き、読み込んでみます。
image = MiniMagick::Image.open('sample.jpg') p image
読み込んだMiniMagick
オブジェクトをp
で表示するとこんな感じです。@tempfile
とあるのが見えるかと思いますが、open
すると画像をTempfile
としてコピーして、それが編集されます。オリジナル画像には編集を加えないのが特長です。
#<MiniMagick::Image:0x007fb9c4289f80 @path="/tmp/mini_magick20160926-30947-1nwlz88.jpg", @tempfile=#<Tempfile:/tmp/mini_magick20160926-30947-1nwlz88.jpg (closed)>, @info=#<MiniMagick::Image::Info:0x007fb9c4289f58 @path="/tmp/mini_magick20160926-30947-1nwlz88.jpg", @info={}>>
画像が見つからないと次のようなエラーが発生します。
#<Errno::ENOENT: No such file or directory @ rb_sysopen - sample.jpg>
画像以外を指定すると次のようなエラーが発生します。
#<MiniMagick::Invalid: `identify /tmp/mini_magick20160926-31462-5q8fym` failed with error:
画像の情報を取得する
パスを取得するにはpath
を使います。
p image.path
#=> "/tmp/mini_magick20160926-6262-1x2fdps.jpg"
いろいろな情報を取得するにはdetails
を使います。
p image.details
#=> {"Base filename"=>"mini_magick20160926-6388-1nx74jz.jpg", "Format"=>"JPEG (Joint Photographic Experts Group JFIF format)", "Class"=>"DirectClass", "Geometry"=>"1600x1062+0+0", "Resolution"=>"400x400", "Print size"=>"4x2.655", "Units"=>"PixelsPerInch", "Type"=>"TrueColor", "Endianess"=>"Undefined", "Colorspace"=>"sRGB", "Depth"=>"8-bit", "Channel depth"=>{"red"=>"8-bit", "green"=>"8-bit", "blue"=>"8-bit"}, "Channel statistics"=>{"Red"=>{"min"=>"0 (0)", "max"=>"255 (1)", "mean"=>"126.904 (0.497664)", "standard deviation"=>"46.5197 (0.18243)", "kurtosis"=>"2.84988", "skewness"=>"-0.36877"}, "Green"=>{"min"=>"3 (0.0117647)", "max"=>"255 (1)", "mean"=>"142.097 (0.557243)", "standard deviation"=>"33.7838 (0.132485)", "kurtosis"=>"2.71775", "skewness"=>"1.84254"}, "Blue"=>{"min"=>"0 (0)", "max"=>"255 (1)", "mean"=>"152.065 (0.596332)", "standard deviation"=>"43.5204 (0.170668)", "kurtosis"=>"-0.0318651", "skewness"=>"1.17011"}}, "Image statistics"=>{"Overall"=>{"min"=>"0 (0)", "max"=>"255 (1)", "mean"=>"140.355 (0.550413)", "standard deviation"=>"41.6311 (0.163259)", "kurtosis"=>"3.26784", "skewness"=>"0.529974"}}, "Rendering intent"=>"Perceptual", "Gamma"=>"0.454545", "Chromaticity"=>{"red primary"=>"(0.64,0.33)", "green primary"=>"(0.3,0.6)", "blue primary"=>"(0.15,0.06)", "white point"=>"(0.3127,0.329)"}, "Interlace"=>"None", "Background color"=>"white", "Border color"=>"srgb(223,223,223)", "Matte color"=>"grey74", "Transparent color"=>"black", "Compose"=>"Over", "Page geometry"=>"1600x1062+0+0", "Dispose"=>"Undefined", "Iterations"=>"0", "Compression"=>"JPEG", "Quality"=>"90", "Orientation"=>"Undefined", "Properties"=>{"comment"=>"Optimized by JPEGmini 3.13.0.4 0x01ee8039", "date:create"=>"2016-09-26T11:54:16+00:00", "date:modify"=>"2016-09-26T11:54:16+00:00", "jpeg:colorspace"=>"2", "jpeg:sampling-factor"=>"2x2,1x1,1x1", "signature"=>"96d0bd9e2b65b05cfc7cf78d156a5074dbfa0afd8a38d800f7518e053d714dd8"}, "Artifacts"=>{"filename"=>"/tmp/mini_magick20160926-6388-1nx74jz.jpg[0]", "verbose"=>"true"}, "Tainted"=>"False", "Filesize"=>"87.5KB", "Number pixels"=>"1.699M", "Pixels per second"=>"169.9MB", "User time"=>"0.010u", "Elapsed time"=>"0:01.010", "Version"=>"ImageMagick 6.7.7-10 2016-06-01 Q16 http://www.imagemagick.org"}
書き出す
何もしていませんが、読み込んだ画像を書き出してみます。write
で書き出せます。
image.write "resize.jpg"
次のように元の名前と同じにすると、上書きになるので注意します。
image.write "sample.jpg"
リサイズする
リサイズするには、resize
を使います。乗算記号はエックス(x)
です。
image.resize "横幅x高さ"
横幅か高さのいずれかの長辺が300px
に収まるように、比率を保ったまま縮小するには次のようにします。
image.resize "300x300" image.write "wh300.jpg"
横幅が300px
に収まるように、比率を保ったまま縮小するには次のようにします。
image.resize "300" image.write "w300.jpg"
高さが300px
に収まるように、比率を保ったまま縮小するには次のようにします。
image.resize "x300" image.write "h300.jpg"
もっといろいろなリサイズ方法については公式サイトに詳しく乗っています。
http://www.imagemagick.org/script/command-line-processing.php#geometry
リサイズで画像が破損する!?
リサイズした画像を再度
リサイズすると次のように画像が破損することがありました。
本来の画像。
横幅400pxへのリサイズに失敗した画像。
どうやら、次のようにリサイズ後に元のファイル名と同じ名前で保存したところ、画像情報がうまく更新されなかったようです。
image = MiniMagick::Image.open('sample.jpg') p image.dimensions #=> [1600, 1062] image.resize "600" image.write "sample.jpg" image = MiniMagick::Image.open('sample.jpg') p image.dimensions #=> [1600, 1062]
2番目のdimensions
は600x398
のはずなのに1600x1062
と認識されていました。2番目の画像ファイル名を変更したところ、うまくいきました。
例)ダウンロードした画像をリサイズする
MiniMagick::Image.open
でURLから直接画像を読み込み、横幅300pxにリサイズします。URLは架空です。
require 'mini_magick' begin uri = 'http://example.com/sample.jpg' image = MiniMagick::Image.open(uri) image.resize "300" image.write "image300.jpg" rescue => e p e end
OpenURI
で画像をダウンロードしたあとに、画像データ
を読み込む場合は次のようにします。
require 'open-uri' require 'mini_magick' begin uri = 'http://example.com/sample.jpg' open(uri) { |io| image = MiniMagick::Image.read(io.read) image.resize "300" image.write "image300.jpg" } rescue => e p e end
OpenURI
で画像をダウンロードしたあとにTempfile
に書き出し、Tempfileへのパス
経由で画像を読み込むには次のようにします。
require 'open-uri' require 'tempfile' require 'mini_magick' begin uri = 'http://example.com/sample.jpg' open(uri) { |io| Tempfile.open { |t| t.binmode t.write io.read t.close image = MiniMagick::Image.open(t.path) image.resize "300" image.write "image300.jpg" } } rescue => e p e end