🦓
[Rails]mini_magickによる画像生成
はじめに
mini_magick
を使って投稿のサムネを作っていきます。
環境
Rails 7.0.4.3
ruby 3.2.1
mini_magick
mini_magick
は、Rubyプログラムで画像処理を行うためのGemです。mini_magick
を使うことで、Rubyから簡単に画像のリサイズ、回転、トリミング、フィルタリングなどの操作を行うことができます。
mini_magick
はImageMagickと呼ばれる画像処理ライブラリをRubyから利用するためのラッパーであり、ImageMagickのコマンドラインツールをRubyでより簡単に使えるようにしてくれます。
前提
ImageMagick
がインストールされていること。
convert -version
で確認できます。
convert -version
Version: ImageMagick 7.1.1-14 Q16-HDRI x86_64 21286 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenMP(5.0)
Delegates (built-in): bzlib fontconfig freetype gslib heic jng jp2 jpeg jxl lcms lqr ltdl lzma openexr png ps raw tiff webp xml zlib
Compiler: gcc (4.2)
mini_magick
をインストールする
Gemfile
gem "mini_magick`"
bundle install
画像生成
テキストを含む画像を生成する時の例です。
require 'mini_magick'
# 画像のパス
input_path = 'input.jpg'
# 画像を読み込む
image = MiniMagick::Image.open(input_path)
# テキストの設定
text = "Hello,\nWorld!\nThis is a\nmultiline text."
font = 'Arial' # 使用するフォント
size = 24 # フォントサイズ
color = 'black' # テキストの色
position = 'center' # テキストの位置 (left, center, right)
offset = '0' # テキストのオフセット位置
# テキストを画像に追加
image.combine_options do |img|
img.gravity position # テキストの位置を設定
img.font font
img.pointsize size
img.fill color
img.draw "text 0,#{offset} '#{text}'" # テキストの内容を指定(改行を含む)
end
# 画像を保存
output_path = 'output.jpg'
image.write(output_path)
サムネカラムを追加する
投稿テーブルにサムネカラムを追加します。
bin/rails g migration AddThumbnailToPost thumbnail:string
invoke active_record
create db/migrate/20230803160727_add_thumbnail_to_post.rb
bin/rails db:migrate
== 20230803160727 AddThumbnailToPost: migrating ===============================
-- add_column(:posts, :thumbnail, :string)
-> 0.0060s
== 20230803160727 AddThumbnailToPost: migrated (0.0060s) ======================
サムネ用メソッドを作成する
投稿を作成される際にタイトルとユーザー名を抽出しサムネを作成します。
app/models/post.rb
class Post < ApplicationRecord
...
before_save :generate_thumbnail
private
def generate_thumbnail
# 画像ファイル名
filename = "#{id}-#{user.name.parameterize}.png"
image = MiniMagick::Image.open(Rails.root.join('app', 'assets', 'images', 'background.png'))
image.combine_options do |cmd|
# タイトル
cmd.font Rails.root.join('app', 'assets', 'fonts', 'Dot-Gothic-16-Regular.ttf')
cmd.size "370x20"
cmd.background "white"
cmd.gravity 'Center'
cmd.pointsize 32
cmd.draw "text 0,0 '#{generate_title(title)}'"
# ユーザー名
cmd.font Rails.root.join('app', 'assets', 'fonts', 'Dot-Gothic-16-Regular.ttf')
cmd.gravity 'SouthEast'
cmd.pointsize 20
cmd.draw "text 10,10 '#{user.name}'"
end
# 保存される場所
thumb_path = Rails.root.join('public', 'thumbnails', filename)
image.write(thumb_path)
# DBに保存
self.thumbnail = "/thumbnails/#{filename}"
end
def generate_title(text)
max_characters_per_line = 8 # 一行に8文字まで
text.to_s.scan(/.{1,#{max_characters_per_line}}/).join("\n")
end
end
Active Storage
を使う場合、イメージをblob
に転換しattach
メソッドを使って保存することができます。
image_blob = StringIO.new(image.to_blob)
self.image.attach(io: image_blob, filename: filename)
app/assets/images/
に背景画像ファイルを用意します。
app/assets/fonts/
にフォントファイルを用意します。
サムネを作成されたことを確認します。
irb(main):005:0> post = Post.last
Post Load (0.3ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT $1 [["LIMIT", 1]]
irb(main):006:0> post.thumbnail
=> "/thumbnails/33-test_user.png"
サムネを表示させる
app/views/posts/index.html.erb
...
<% @posts.each do |post| %>
<% if post.thumbnail.present? %>
<%= image_tag post.thumbnail %>
<% else %>
<%= image_tag 'default_thumbnail.png' %>
<% end %>
<% end %>
オプション
他にも多くのオプションがあります。
img.quality '80' # 生成されたJPEG画像のクオリティを80%に指定
img.background 'white'`, `'red'`, `'#FF0000' # 背景色を指定
img.composite # 画像を合成 別の画像を指定の位置に重ねることができる
img.rotate "-90" # 画像を反時計回りに90度回転
img.flip # 画像を上下反転
...
オプション一覧を見る
magick -list
でオプション一覧を見ることができます。
➜ magick -list style
Any
Italic
Normal
Oblique
➜ magick -list weight
Thin
ExtraLight
UltraLight
Normal
Regular
Medium
DemiBold
SemiBold
Bold
ExtraBold
UltraBold
Heavy
Black
➜ magick -list font
...
おわりに
mini_magick
は簡単の画像の作成や合成には便利ですね。
Discussion