10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MiniMagick(ImageMagick)についてのメモ

Posted at

概要

Rails学習者なら一度は使用したことがあるであろう有名なGem「MiniMagick」について、詳しく調べてみると学びが多かったのでまとめてみました。
実務経験を積んでいる方なら当たり前の知識かもしれませんが、深く考えずにGemを使用していた私にとっては興味深い内容でした。

そもそも「ImageMagick」を各言語で使いやすくしたものの一つがMiniMagickということすら知りませんでした。(^^;;)
同じようなレベルの方にとっては面白い内容だと思います。
https://imagemagick.org/script/develop.php

環境

ruby 2.7.1
ImageMagick 7.0.10-23
MiniMagick 4.10.1

ImageMagickの脆弱性

ImageMagickは扱えるファイルの数が多いことなどから、脆弱性が多く報告されており、使用の際は環境に応じた対策をとる必要があるようです。

参考

さようなら ImageMagick
「さようなら ImageMagick」の考察
ImageMagickを使うWebアプリのセキュリティ

【実験】Railsのよく紹介されているようなバリデーション

例えば以下のバリデーションでは、sample.pdfというファイルをsample.jpgと拡張子を書き換えただけでバリデーションに掛からなくなります。

def image?(picture)
  picture.content_type.in?(%("image/jpeg image/jpg image/png")) && picture.content_type != ""
end

ローカル環境で試しにsample.pdfsample.jpgに書き換えて以下のコードを実行し、書き出されたファイルの拡張子をpdfに戻したところ、pdfとして表示することができました。
また、typeは拡張子のJPEGではなくpdfのAIとして認識されます。

sample.rb
require "mini_magick"
image = MiniMagick::Image.open("sample.jpg")
puts image.type
image.write("output.jpg")

=> AI

危険性についてはうまく説明できませんが、想定していたバリデーションを簡単に抜けられていることを考えると怖いですね。
参考記事では、policy.xmlを設定するように紹介していましたが、MiniMagickでの方法がよく分からなかったので、調べ次第追記します。
簡易的にこんなのもありかな??

types = [ "JPEG", "PNG" ]
types.include?(image.type)

最適化と実行速度

resizeとstripオプションくらいしか使用したことがなかったのですが、ImageMagickには他にも多くのオプションが用意されており、MiniMagickでも全てのオプションを使用することができます。

GoogleDevelopersで紹介されていたJPEG画像の最適化コードを元に簡単な実験をしてみたのですが、実行方法次第で4倍ほど実行速度に差がありました。

参考

画像を最適化する
ImageMagick の JPEG オプション

サンプルコード

使用画像:
サイズ: 10.8M
大きさ: 6000×6000

sample.rb
require "bundler/setup"
require "mini_magick"
require 'benchmark'

result = Benchmark.realtime do
  MiniMagick::Tool::Magick.new do |magick|
    magick << "images/test.jpg"
    magick.sampling_factor "4:2:0"
    magick.strip
    magick.interlace "JPEG"
    magick.colorspace "sRGB"
    magick.quality "85"
    magick << "output.jpg"
  end
  #処理概要 2.2035720000058063s
  #処理概要 2.2015189999947324s
  #処理概要 2.204152000005706s
  #サイズ 10.8M => 4.9M

  convert = MiniMagick::Tool::Convert.new
  convert << "images/test.jpg"
  convert.sampling_factor "4:2:0"
  convert.strip
  convert.interlace "JPEG"
  convert.colorspace "sRGB"
  convert.quality "85"
  convert << "output.jpg"
  convert.call
  #処理概要 2.202056000001903s
  #処理概要 2.1908320000002277s
  #処理概要 2.207652999997663s
  #サイズ 10.8M => 4.9M

  image = MiniMagick::Image.open("images/test.jpg")
  image.sampling_factor "4:2:0"
  image.strip
  image.interlace "JPEG"
  image.colorspace "sRGB"
  image.quality "85"
  image.write("output.jpg")
  #処理概要 9.05225000000064s
  #処理概要 9.08197300000029s
  #処理概要 8.971012000001792s
  #サイズ 10.8M => 5.4M

  cmd = "convert images/test.jpg -sampling-factor 4:2:0 -strip -quality 85 -interlace JPEG -colorspace sRGB output.jpg"
  system cmd
  #処理概要 2.168391999999585s
  #処理概要 2.064037999996799s
  #処理概要 2.167836000000534s
  #サイズ 10.8M => 4.9M
end

puts "処理概要 #{result}s"

あとがき

「実行速度遅いんだよな〜」「思ったより圧縮されないんだよな〜」と思いつつも、表面撫でたような調べ方しかしていなかったので、ImageMagickがこんなにも高機能なソフトウェアだと知りませんでした。
MiniMagickの書き方も色々あったんですね。
MiniMagick::Image.openMiniMagick::Image.newくらいしか使っていなかったので驚きでした。
そして、全てREADMEに書いてあったのも...

日本語記事に甘えず、まずはREADMEを隅々まで読もうと、もう何度目になるか分からない決意を新たにしました。。。

10
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?