(ruby)(RMagick)(ImageMagick)(Imageクラス と ImageListクラス の 基本)

 さてさて RMagickに関して いろいろと 勉強中な日々なんですが
ドキュメントやリファレンスが英語なので なかなか 捗らない 笑)
高校の英語の点数が赤点間際だった私には酷な話なワケです 笑)

 ということで まず断っておく事は
このRMagickの記事は『あくまで 現在の所 私はそういう風に思っている』
程度の認識で書いてます、 嘘も平気で書いている可能性も 十分にあるので
『ド素人の ruby(RMagick)奮戦記』程度の 感覚で読んでください

 今回は 超基本的なところで
Imageオブジェクト と ImageListオブジェクトについてです
rubyの場合はクラスと言った方がしっくり来るのかな?)

 Imageオブジェクトとは その名の通り 一枚の絵のオブジェクトですね
メソッドなどは
http://studio.imagemagick.org/RMagick/doc/index.html
Image (attribute methods)
Image (class methods and instance methods a-d、e-o、p-w)
を参照のことです

 Imageオブジェクトに一枚の絵を読み込む場合は、 readクラスメソッドを使います
ドキュメントには Image.read(filename) [ { optional arguments } ] -> array
とされていますので
require 'RMagick'
img1 = Magick::Image.read("abcdefg.jpg")[0]
ということになりますね
何故配列なのかというと アニメーションgifファイルなどを考慮しての事だと思います

 また 新規作成の状態で 生成することも出来ますよね、 newクラスメソッドですね
ドキュメントには Image.new(columns, rows [, fill]) [ { optional arguments } ] -> image
とされていますので
Magick::Image.new(400, 300) などとすれば 400x300 の 新しい画像が生成されます

 今回は ImageListを使ってみる所まで 書こうと思っているので
二枚目は img1と同サイズの 背景が透明のものを生成してみます
img1 の 生成から 一括して書くとこうなります
require 'RMagick'
img1 = Magick::Image.read("abcdefg.jpg")[0]
img2 = Magick::Image.new(img1.columns, img1.rows){self.background_color = "none"}
これで img1 に abcdefg.jpgがロードされ、 img2 に img1と同サイズの 透明な画像が生成されます

 ここから ImageListの話になります
ImageListとは その名の通り ImageをListしたものです 笑)
実は PhotoShopなどで言う レイヤーと同じような概念で捉えることが出来ます
Imageを ImageListに 詰め込んでいくと 上にどんどん重ね上げていく事に等しくなるようです

 ImageList の アトリビュート や メソッドは
http://studio.imagemagick.org/RMagick/doc/index.html
ImageList (http://studio.imagemagick.org/RMagick/doc/ilist.html)を参照のことです

 ImageList の 新規作成は newクラスメソッドですね
Magick::ImageList.new [ { optional arguments } ] -> imagelist となっていますので
imglst = Magick::ImageList.new() と 書く事になるわけですね

 では さっきの img1 と img2 を ImageListに詰め込むまでの処理です
require 'RMagick'
img1 = Magick::Image.read("abcdefg.jpg")[0]
img2 = Magick::Image.new(img1.columns, img1.rows){self.background_color = "none"}
imglst = Magick::ImageList.new()
imglst[0] = img1
imglst[1] = img2
 これで ImageListの中身は
最上層 imglst[1] 透明な画像
最下層 imglst[0] abcdefg.jpgの画像
と なっているはずです
もし きちんと レイヤーのようになっているのなら
imglst[1] に 何かを描き込め、と命令すれば imglst[1]に それが 描かれるはずです
(もちろん imglst[0]には 影響を与えない)

 ということで 今回は Drawオブジェクトを使って 角の丸い四角形を 描いてみます
Draw の 詳しい説明は また後日という事で コードだけを書くと
Magick::Draw.new{
  self.fill = "white"
}.roundrectangle(30, 30, imglst[1].columns-30, imglst[1].rows-30, 20, 20).draw(imglst[1])
imglst[1] よりも 縦横60px小さい 角丸四角形が imglst[1] に 白色で描き込まれます
最上層 imglst[1] 透明な背景に白い角丸四角形が描かれた物
最下層 imglst[0] abcdefg.jpgの画像

 では 思惑通り abcdefg.jpg の上に 白い角丸四角形が 描かれた物になっているのかの確認をします
レイヤーを統合して 書き出すには
imglst.flatten_images.write("xxxx.png")
とします、 flatten_imagesでレイヤーを統合し、 writeで 書き出すわけですね

 では ここまでの流れを まとめます
require 'RMagick'

img1 = Magick::Image.read("abcdefg.jpg")[0]
img2 = Magick::Image.new(img1.columns, img1.rows){self.background_color = "none"}

imglst = Magick::ImageList.new()
imglst[0] = img1
imglst[1] = img2

Magick::Draw.new{
  self.fill = "white"
}.roundrectangle(30, 30, imglst[1].columns-30, imglst[1].rows-30, 20, 20).draw(imglst[1])

imglst.flatten_images.write("xxxx.png")
 これで abcdefg.jpg の上に 角丸四角形が 描かれた xxxx.pngという画像が出来上がります

 もちろん いちいち img1 や img2 に一旦 代入しなくても
ダイレクトに ImageListに Imageオブジェクトを投げ込むことも出来ますね
require 'RMagick'

imglst = Magick::ImageList.new()
imglst[0] = Magick::Image.read("abcdefg.jpg")[0]
imglst[1] = Magick::Image.new(imglst[0].columns, imglst[0].rows){self.background_color = "none"}

Magick::Draw.new{
  self.fill = "white"
}.roundrectangle(30, 30, imglst[1].columns-30, imglst[1].rows-30, 20, 20).draw(imglst[1])

imglst.flatten_images.write("xxxx.png")