RMagickを使ってアプリ用のサンプル画像を量産しよう
やりたいこと
あなたはiOSアプリを開発しているとします。
一週間後に、デザイナーからimage1.png
からimage100.png
までの100枚の画像リソースが届きます。あなたはこの画像をアプリに組み込んで表示しなければいけません。
しかし、デザインが届くのを待ってから開発に着手するのでは開発が遅れてしまいます。お客さんが激おこぷんぷん丸になります。
仕方ないので、とりあえずは仮の画像を当てて作業することにします。
Placehold.it - Quick and simple image placeholders などを利用して仮の画像を作ってもいいのですが、それでは..
「image15.png
を入れるべき場所にimage37.png
を入れちまってた!!やべえ!!」
っていうケアレスミスを開発時点で気づくことができません。
それでは、画像自体にidを記載してしまいましょう。
image1.png
には「1」って書いて、image57.png
には「57」って書いて、image100.png
には「100」って書けばいいんです。
...でも、どうやって?手作業??100枚も???
「ちょっとした画像加工を多数の画像に対して行う」のを手作業で行うなんて耐えられない
— 定食屋 おろポン (@oroponya) 2014, 5月 13
僕は耐えられません。目の前の箱に働いてもらいましょう。
※ 状況設定はフィクションです。スマホアプリ開発に限らず、Webアプリ開発でもなんでも使えます。
準備する
Homebrew
でimagemagick
を入れる。
% brew install imagemagick
bundler
でrmagick
を入れる。別にgem install rmagick
でもいい。
% bundle init % echo gem \"rmagick\" >> Gemfile % bundle install Fetching gem metadata from https://rubygems.org/.. Resolving dependencies... Installing rmagick 2.13.2 Using bundler 1.6.2 Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.
Sample用にoctcat.png
を仕入れてくる。octcatかわいい。
% curl -o octcat.png https://octodex.github.com/images/original.png
情報収集
準備は万端。ドキュメントから必要な情報を仕入れる。
http://www.imagemagick.org/RMagick/doc/usage#drawing_on.html
The annotate method draws text on an image.
「annotateメソッドは画像にテキストを描画します。」
面倒くさいので英語はすっ飛ばしてサンプルコードだけ見る。
#! /usr/local/bin/ruby -w require 'RMagick' # Demonstrate the annotate method Text = 'RMagick' granite = Magick::ImageList.new('granite:') canvas = Magick::ImageList.new canvas.new_image(300, 100, Magick::TextureFill.new(granite)) text = Magick::Draw.new text.font_family = 'helvetica' text.pointsize = 52 text.gravity = Magick::CenterGravity text.annotate(canvas, 0,0,2,2, Text) { self.fill = 'gray83' } text.annotate(canvas, 0,0,-1.5,-1.5, Text) { self.fill = 'gray40' } text.annotate(canvas, 0,0,0,0, Text) { self.fill = 'darkred' } canvas.write('rubyname.gif') exit
ImageList.new
でキャンバスを初期化
Draw.new
で描画オブジェクトを初期化
描画オブジェクトにプロパティを設定し、annotate
メソッドで描画を行う。
annotate
メソッドに渡すブロック内でfill
を指定することで、文字の塗りつぶしを行う。
write(fpath)
でファイルに書き込む。
このコードではテキストの描画位置と色を変えて複数回描画することで、凹凸(ベベルとエンボス)を表現している。
fmfm。なんとなく理解したらおk。次に進む。
書いてみる
サンプルコードを元に細かい修正を加える。 細かいところはコメントに書いた。
require 'RMagick' include Magick # 面倒くさいのでinclude Text = "Hello, My name is Octcat!" img = ImageList.new 'octcat.png' # ImageList.new file_path で画像読み込み text = Draw.new # 描画オブジェクトを初期化 text.font = '/System/Library/Fonts/Avenir Next.ttc' # フォントはフォント名だけではなく絶対パスで指定 text.pointsize = 52 text.gravity = CenterGravity # 上下中央寄せしてくれるみたい text.annotate(img, 0,0,0,0, Text) { self.fill = 'gray' # カラーコードか色名を入れる } img.write('octcat_greeting.png') # 書き出し
ね、簡単でしょう?
注意点として、少なくとも手元のMacでは、fontにフォントの絶対パスを指定する必要があった。
パスがわからない場合は、Font Book.app
でフォントを検索して、右クリックからShow in Finder
してファイルパスを調べればおk。
量産してみる
文字を縁取りし、量産してみる。
注意するところは、Line29のimg.copy
。copy
メソッドを呼んでdeep copyを行わないと、同じ画像に対して何度もテキストを上書きすることになってごちゃごちゃになる。
iOS用にRetina用と非Retina用の画像を量産するならこんな感じで行ける。(てきとう)
require 'RMagick' include Magick id_min = 0 id_max = 100 def annotate_id img, id, thumb=false fname = "Octcat_%03d#{'@2x' unless thumb}.png" % id scale = thumb ? 0.5 : 1.0 img = img.scale(scale) text = Draw.new text.font = '/System/Library/Fonts/Avenir Next.ttc' text.pointsize = (1500 / fname.length) * scale text.gravity = CenterGravity text.annotate(img, 0,0,0,0, fname) { # 画像の色にかかわらず文字が読めるように縁取りする self.stroke_width = 3 * scale self.stroke = 'white' self.fill = 'gray30' } img.write(fname) end img = ImageList.new 'octcat.png' id_min.upto(id_max) do |i| annotate_id img.copy, i annotate_id img.copy, i, true end
まとめ
ImageMagickを使ったことなくて焦ったけど、意外と簡単に使えた。みんなも使おう。
目の前の箱のマスターとなってビシバシ働いてもらおう。