selflearn @ ウィキ

Alpha Compositing - Part I

最終更新:

匿名ユーザー

- view
メンバー限定 登録/ログイン

Alpha Compositing - Part I


開始日 2007年02月09日
最終更新日 2009年06月08日

はじめに

アルファコンポジットについての基本的な説明・使い方を記しています。

原著


「Alpha Compositing - Part I」
http://rmagick.rubyforge.org/src_over.html

注意

  • もともと個人利用を目的として日本語化したために、けっこう意訳している部分があります。「意味分からないよ」とか「おかしいんじゃない?」とかいうのがあれば、オリジナルを参照するか、コメントで質問してください(がんばって調べます)。

用語

訳文に出てくる各語に対応する原文と意味を以下に記します。

訳語 原文 意味
元画像 source image 合成しようとしている画像。
合成先画像 destination image 元画像の下に重ねる画像。

更新履歴

  • 2007/2/9 作成開始
  • 2007/2/20 とりあえず一通りの日本語訳が完了。時間がかかってしまった・・・。
  • 2008/3/17 ソースコードを引用ではなく専用のタグで記述。読みやすくなった。


訳文


変わった形をした写真をサムネイルコレクションに加えたいとき、君はどうやっている?たとえば風景の写真集にポートレートを加えるときとかね。画像が長方形にすらなっていないものもある。
こういった画像を扱う解決方法の1つとして、「枠」となる画像にそれらをはめこんで(ブレンドして)しまう方法がある。RMagickのcompositeを使って、ね。

アルファコンポジット - 2つの画像を1つに

画像処理において、アルファコンポジットとは数学的処理により2つの画像を結合し、1つの合成画像を作り出すことだ。アルファコンポジットの伝統的な計算モデルは「Porter-Duff」モデルと言われていて、12種類の合成手法を定義している。
そこで本記事ではsrc-overと呼ばれる、Porter-Duffモデルのなかでももっともシンプルでよく使う処理方式について、使用方法を紹介しよう。

src-overの意味は以下のとおりだ。

合成先画像のピクセルを元画像のピクセルによって置き換えること。

ただし、もし元画像が半透明・不透明なピクセルを持っているなら、ルールは若干複雑になる。

合成先画像のピクセルを元画像のピクセルによって置き換える。ただし元画像に半透明または不透明なピクセルがある場合、合成先画像のピクセルは一部または完全に透けて見える。

RMagickによるアルファコンポジット

RMagickは、ImageMagickまたはGraphicsMagickライブラリのRubyバインディングだ。どちらのライブラリでも、Magick::Imageクラスのメソッドとしてアルファコンポジット用のAPI:compositeメソッドを用意してくれている。
このcompositeメソッドには4つの情報が必要だ。

  1. 合成先画像(destination image)。これはMagick::Imageのインスタンスで、compositeメソッドを呼ぶときのレシーバだ。
  2. 元画像(source image)
  3. 元画像を合成先画像のどこに配置するか(position)
  4. 適用する合成方法

compositeメソッドは、元画像を合成するときの場所を柔軟に指定できるよう少しずつ変わってきた。その結果として、今では3種類の引数の渡し方で使用できるようになっている。
合成先画像に対する元画像の配置場所をどう表現するか、が違うんだ。

まず最初に、オフセットをx-y座標のペアで設定する方法を紹介する。
result = dst.composite(src, x, y, comp_op)
ここでのdst,srcはそれぞれ合成先画像、元画像を意味している。x,yと書かれた第2,3引数で、合成先画像の左上端を原点としたオフセット量を指し示すんだ。*1
ちなみにx,yには負の値も設定可能で、たとえばxで負値をセットした場合は元画像が合成先画像よりも左側に配置される。yでセットした場合は、合成先画像より上に配置される、というわけだ。
最後の引数(comp_op)は合成方法の種類で、どういった合成方法にするかをMagick::CompositeOperatorクラスの中から1つ選ぶ。

2つ目は、x-yのオフセット量を指定する代わりにMagick::GravityTypeを指定する方法だ。
result = dst.composite(src, gravity, comp_op)
gravity以外の引数はさっきと同じで、元画像と合成方法だ。

GravityTypeには以下の9種類が提供されている:
NorthWestGravity
元画像を合成先画像の左上端に配置
NorthGravity
元画像を合成先画像の上部中央に配置
NorthEastGravity
元画像を合成先画像の右上端に配置
EastGravity
元画像を合成先画像の中央右端に配置
SouthEastGravity
元画像を合成先画像の右下端に配置
SouthGravity
元画像を合成先画像の下部中央に配置
SouthWestGravity
元画像を合成先画像の左下端に配置
WestGravity
元画像を合成先画像の中央左端に配置
CenterGravity
元画像を合成先画像の中心に配置

そして3つ目の方法はGravityTypeとx-yオフセットの両方を指定する方法だ。この方法ではGravityTypeで示す値の意味がx,yによって変化する。
result = dst.composite(src, gravity, x, y, comp_op)
これもさっきと同じで、src,dst,comp_opの指す意味は同じだ。もちろんgravity,x,yも使う値(クラス)の型は変わらない。ただし、

  1. gravityがNorthEastGravity/EastGravity/SouthEastGravityのいずれかの場合、xは画像の右端からのオフセット量になる(元は左端からのオフセットを示す)。
  2. gravityがSouthEastGravity/SouthGravity/SouthWestGravityのいずれかの場合、yは画像の下端からのオフセット量になる(元は上端からのオフセットを示す)。
  3. それ以外はgravity引数は無視され、x,yのみ2つ目と同様に左上端からのオフセット量として用いられる。

となる。繰り返すが、3つ目の方法でもx,yには負値を設定できる。このときのgravityとx,yの関係には十分注意してほしい。

長方形の画像を正方形の枠で囲う

さっきも言ったように、srs-over処理による画像の合成は、合成先画像のピクセルを元画像の対応するピクセルで置き換えることで画像を生成する。もし元画像が合成先画像よりも小さければ、合成先画像の一部だけが元画像によって置き換えられる。この特徴によって、正方形の背景(の一部)に長方形の画像を配置することが出来るわけだ。

ここで1つ例を挙げよう。左側の画像は80x100サイズのサムネイルで、これを中央にある金色の画像(128x128サイズ)に合成しようとしている。右側の画像は合成結果で、合成先画像と同じサイズだ(訳注:後述する「元画像が合成先画像よりも大きかったら」を参照)。元画像はsrc-over処理によって合成先画像の上に配置されている。


#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
元画像 合成先画像 合成結果

以下はこの合成処理を実現するスクリプトだ。
1  require 'RMagick'
2
3  gold_fill = Magick::GradientFill.new(0, 0, 0, 0,
                                        "#f6e09a", "#cd9245")
4
5  dst = Magick::Image.new(128, 128, gold_fill)
6  src = Magick::Image.read("composite1-src.gif")[0]
7
8  result = dst.composite(src, Magick::CenterGravity,
                          Magick::OverCompositeOp)
9  result.write('composite1.gif')
  • Lines 3-5 :合成先画像を128x128のサイズ+金色のグラデーションで作成
  • Line 6 :サムネイル化する元画像をファイルから読み込み
  • Line 8 :compositeメソッドによる合成画像の作成。この例では2つ目の方法で引数を渡している。Magick::CenterGravityで元画像を合成先画像の中央に配置し、Magick::OverCompositeOp方式で上書きする。

複雑な形の画像を正方形の枠で囲う

ここではsrc-over方式の、一部が透明になった画像のケースについて紹介する。
まずはsrc-overの定義を思い出してほしい。

合成先画像のピクセルを元画像のピクセルで上書きする。ただし元画像の一部または全部が透過色である場合、合成先画像のピクセルが透けることになる。

合成先の画像がどのくらい透けて見えるかは、元画像の透明度に依存する。上の例のような100%不透明なピクセルであれば元画像は合成先画像を完全に隠してくれるし、もし元画像が50%程度の透明度を持っていれば、合成先の画像は半分くらい透けて見えることになる。

下の例では、元画像として左側のペンギンのおもちゃを取り扱う。この画像はPNGフォーマットで、ペンギンの周りが透明になっている。合成先画像は128x128サイズの"plasma"画像だ。右側の合成結果ではsrc-over処理によって元画像の不透明な部分のみ合成先画像に上書きされている。実際にはペンギンの周りにある透明なピクセルも合成されているんだけど、透明(つまり0%不透明という意味だ)なだけに合成先の画像が透けて見えているわけだ。


#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
#ref error :画像を取得できませんでした。しばらく時間を置いてから再度お試しください。
元画像 合成先画像 合成結果

以下はこの合成処理を実現するスクリプトだ。
1  require 'RMagick'
2
3  dst = Magick::Image.read("plasma:fractal") {
             self.size = "128x128"}.first
4  src = Magick::Image.read('tux.png').first
5
6  result = dst.composite(src, Magick::CenterGravity,
                          Magick::OverCompositeOp)
7  result.write('composite2.gif')
 
  • Line 3 :組込みの"plasma"フォーマットを使って128x128サイズの合成先画像を作成
  • Line 4 :サムネイル画像(元画像)の読み込み
  • Line 6 :合成画像の作成。前例と同じ引数でcompositeメソッドを呼んでいる

元画像が合成先画像よりも大きかったら

元画像が合成先画像よりも大きかった場合、元画像のうち合成先画像の範囲外になるピクセルは無視される。つまり、合成結果は常に合成先画像と同じサイズになるんだ。このときx,y,gravityは元画像のどの部分を合成するかを制御する目的で使うことになる。

その他の合成方法

RMagickではImageクラスのcomposite以外にも合成用のメソッドを2つ用意している。まず、Drawクラスのcompositeメソッドだ。このメソッドは以下のように使う。
gc.composite(x, y, width, height, src_image, comp_op)
 
合成先画像はドロー画像で、えっとつまり、drawメソッドに渡す引数だ。x,yは合成先画像の左上端からのオフセット量で、width,heightで元画像のスケール(倍率)を指定できる。(width,heightを0にセットすれば拡大/縮小しないで合成できる)

もう1つは、RVG*2のRVG::GroupとRVG::Patternクラスが持つimageメソッドがある。これは背景イメージ上にラスターイメージを合成するメソッドだ。ただしこのメソッドはcomp_op引数を持たず、常にsrc-overで合成するよ。

参考サイト

いつものように、Anthony ThyssenのすばらしいサイトではImageMagickを使ったアルファコンポジットについてのもっと詳しい情報が載っている。アルファコンポジットとPorter-Duffモデルについて分かりやすい説明ならこのページを見てくれ。あと、「SVG 1.2 Specification」のページではアルファコンポジットの説明が、数学的説明と共に載っている。

Tim - Feb 18, 2006


参考サイト(訳者による追加)




-

コメント

コメント大歓迎です。ただ、スパムなど内容によっては独断で削除する場合があります。あらかじめご了承ください。

名前:
コメント:

タグ:

RubyRMagick
記事メニュー
最近更新されたページ
注釈

*1 訳注:原文ではrelativeという表記がありますが、ここで指定する値が相対値か絶対値のどちらかは、後日確認してみます。→(2007/2/20)ピクセル指定の絶対値でした。

*2 訳注:RVG=Ruby Vector Graphics