⚠️ これは 非公式の翻訳サイトです。ImageMagick Studio LLC とは無関係です。正確な情報は 原文(https://usage.imagemagick.org/mapping/index.html) を参照してください。

ImageMagick 使用例 -- 画像マップ効果

ImageMagick 使用例 前書きと索引
画像マッピング入門
画像マッピングによる画像の歪み
絶対歪みルックアップマップ

何らかの二次的な「マップ」画像を使って処理を制御し、画像を歪めたり変更したりします。色を置き換えたり、画像を可変的にぼかしたり、ソース座標を絶対的または相対的に指定して画像を歪めたりといった処理です。


入門

合成単純なワーピング歪みに関する前のセクションで見てきたように、画像はさまざまな方法で変更できます。しかしそれらはすべて、ImageMagick に組み込まれた特定の手法に限定されています。「FX」DIY 演算子を使えば自分独自の画像歪みを「自作」することもできますし、EvaluateFunction のような演算子、あるいはさまざまな Level 演算子を使って画像の値を直接変更することもできます。しかし歪みはその処理を行うために多くの計算(と時間)を要し、同じ処理を複数の画像に対して行おうとする場合、IM にそれらの計算をすべて繰り返させるのは本当に時間の無駄になりかねません。もう一つの側面は、歪みの効果を自由な形で限定するのが非常に難しいということです。適用したい歪みを単純に編集したり変更したりすることができません。制御が限られているのです。画像マッピングは違います。追加の「マップ」画像を使って、画像のどの部分を、どれだけ、あるいはどのように変更するかを制御します。画像全体を変更する必要はありませんし、あらかじめ定義された、あるいはあらかじめプログラムされた方法で変更する必要もありません。画像を_あらゆる_可能な方法で、制限なく変更できる「マップ」を作成できます。また、マッピングを_編集_したりさらに変更したりして、その効果を調整したり限定したり、異なるマップを統合したり、効果を滑らかにしたりぼかしたりして、より複雑にすることもできます。そして最後に、後で再び使うためにマッピングを_保存_できます。結果を制御するのは「マップ」画像です。変更が「マップ」によって制御されるため、ImageMagick が行う必要のある計算は通常ごくわずかであり、そのため「画像マッピング」は一般に_非常に高速_です。また_繰り返し可能_でもあり、同じ非常に複雑なマップを任意の数の画像に適用して、まったく同じ変更を得ることができます。つまり、画像ディレクトリ全体に対して非常に高速に適用できるのです。本質的に_画像マッピング_が行うのは、特定の効果の遅く複雑な数学的処理を、特定の画像から、より汎用的な「マップ」画像へと移すことです。いったんその「マップ」が生成されれば、それを多数の実際の画像に非常に高速に適用できます。

画像マップとは何か

マッピング画像は基本的に「ルックアップテーブル」または LUT であり、特定の効果を画像に対して個々のピクセル単位でどのように適用すべきかを定義します。つまり、効果が適用されるかどうか、そしてどの程度適用されるかは、完全に画像マップによって制御されます。本質的に画像は値の配列であり、それらの値が何を意味するかは適用されているマッピング処理に依存します。それらは次のようなものを示しうります……

  • 直接の置換値(色のルックアップ)、
  • 色がどの画像から来るべきか(画像マスキング)、
  • ピクセルをどれだけ明るくまたは暗くすべきか(ハイライト)、
  • ソース座標の指定(歪み)、
  • あるいは現在位置に対する相対的な位置(変位)。
  • この位置のピクセルをどれだけぼかすか

これらの多くはすでに画像合成で見てきましたし、ある意味で画像マッピングは複数の画像を統合するもう一つの方法にすぎません。実際、多くの画像マッピング技法は単に特殊な合成メソッドとして実装されています! ただし真の画像合成とは、本当は二つの実際のカラー画像をさまざまな方法で重ねること(具体的には Duff-Porter アルファ合成メソッド)にすぎないことを覚えておいてください。画像マッピングはより一般的に、一つの画像を特別な方法で変更する特殊な画像を使うことを伴います。画像マッピングについて最も難しい部分は、特定の効果のための特定の「マップ」を生成することです。そしてこれこそが、このページに掲載されている多くの作業、労力、技法が関わっている部分です。しかしいったんマップを手に入れれば、それを多くの異なる画像に対して何度も非常に高速に使えます。


画像マッピングによる画像の歪み

IM 使用例の前のセクション(単純な画像ワーピング一般的な画像歪みなど)で説明したさまざまな歪み演算子は、IM グラフィックスライブラリにプログラムされたさまざまな種類の歪みに限定されており、一般に特定の数式や公式を使います。しかし、より自由な形で、あまり数学的でない方法で自分独自の歪みを設計したい場合もあります。たとえば、画像を特定の形にマッピングしたり、特定の複雑なレンズ効果を持たせたりといった、より複雑な歪みを生成する場合、数学的に定義するよりも描いたほうが簡単です。また、単に多数の画像に対して歪みを繰り返し、歪みを何度も再計算しなくて済むようにしたいだけのこともあります。解決策は、歪みをあらかじめ計算し、それをグレースケール画像の形をした特別なルックアップテーブル(LUT)として保存することです。つまり、出力ピクセルごとに LUT をルックアップし、その値を使ってソース画像から色をルックアップします。すなわち、3つのステップが必要です。

  1. 各出力先ピクセルを LUT でルックアップする
  2. LUT 値をソース画像の位置にマッピングする(2つの方法)
  3. ソース画像から色をルックアップする

歪みの「ルックアップテーブル」として画像が使われるため、'Gimp' や 'PhotoShop' のような画像エディタを使って歪みマップを作成または変更でき、本当に凝った複雑な歪みを行う自由が得られます。ただし、これまで見てきた他のすべての歪みメソッドと同様に、ルックアップは逆ピクセルマッピングとして適用されることを覚えておかなければなりません。つまり、出力先画像の各ピクセルについて、適用されている歪みメソッドを使ってソース画像からそのピクセルの色をルックアップします。この場合、メソッドは提供されたルックアップテーブル画像からソース座標をルックアップすることです。
さて、画像マップを使ってソース画像のどこで色をルックアップすべきかを決める方法には2通りあります……絶対または相対です。絶対座標ルックアップでは、歪みマップが LUT の色値を、色をルックアップするソース画像内の座標へ直接変換します。LUT 内の色がどこにあるかは関係なく、各色が使うべき正確なルックアップ点を指します。歪み LUT 画像には色のグラデーションがありますが、そのグラデーションがどのようにワーピングまたは歪められても、マップが適用されたときには同じ効果が得られます。相対座標ルックアップでは、変位マップが色値を使って現在の座標をオフセットし、色をルックアップするソース画像内の位置を割り出します。これは、純粋なグレーの LUT 画像が使われ、明るい領域と暗い領域がマップ内の位置に関わらずピクセルをどのようにシフトまたは変位させるかを定義することを意味します。後で見るように、両方のメソッドには利点と欠点があります。


絶対歪みルックアップマップ

絶対歪み LUT マップの作成は、理解する点でも、歪み LUT マップを作成する点でも、適用する点でも、2つの方法のうち単純なほうです。しかし、後で見るように、これには非常に深刻な欠点があり、相対変位マップより実用的でなくなっています。「歪みマップ」内の特定の点での色が、ソース画像内の位置を直接指します。つまり、「マップ」全体のグレースケールグラデーションが、その位置に置かれるべき「テクスチャ」を定義します。さて、マップ画像が実際には Tシャツのような複雑なオブジェクトの画像で、複雑なしわや波があると考えてみてください。そのシャツにグラデーションがあれば、任意の平らな画像をそのシャツ上にマッピングできます。それが絶対歪みマップの力です。LUT 画像内の「黒」のピクセル(色値 0)は、ソース画像の最も左のピクセル、すなわち '0' の X 座標と見なされ、LUT 内で「白」のもの(値 1)は、最も右のピクセル(ソース画像の幅)と見なされます。この LUT はソース画像内の色の X または水平位置のみをルックアップすることに注意してください。色の高さや Y 位置は変更しません。では、LUT として単純な平凡なグレースケールの水平グラデーションを使ってこれを試してみましょう。

  magick koala.gif \( -size 75x75 gradient: -rotate 90 \) \
          -fx 'p{v*w,j}'      distort_noop.gif

[IM Output] [IM Output] [IM Output]

これはソース画像から出力先画像へのマッピングにおいて実際の変化を一切生じませんでした。それは、歪みマップからルックアップした X 座標が、色をルックアップしていたまさにその位置と同じだったからです。単にグラデーションを反転させるだけで、ピクセルのルックアップも反転し、鏡像が生成されます。つまり、白が左、「黒」が右になり、画像全体に水平グラデーションができます。

    magick koala.gif \( -size 75x75 gradient: -rotate -90 \) \
          -fx 'p{v*w,j}'      distort_mirror_x.gif

[IM Output] [IM Output] [IM Output]

元のグラデーションをコントラスト強調演算子で圧縮すると、はるかに有用な歪みが得られます。

  magick -size 75x75 gradient: -rotate 90 \
          -sigmoidal-contrast 8,50%      map_compress.gif
  magick koala.gif  map_compress.gif -fx 'p{v*w,j}'  distort_compress.gif

[IM Output] [IM Output] [IM Output]

歪みの両端が引き伸ばされる一方、中央が圧縮されていることに注目してください。2つの歪みマップ、一つは X 座標を調整するもの、もう一つは Y 座標を調整するものを使うことで、これを2次元に拡張できます。

  magick map_compress.gif -rotate 90 map_compress_y.gif
  magick koala.gif  map_compress.gif map_compress_y.gif \
          -fx 'p{u[1]*w,u[2]*h}'   distort_compress_2D.gif

[IM Output] [IM Output] [IM Output] [IM Output]

ご覧のように、上記は爆縮メソッドの一種を再現していますが、Implode 演算子が放射状に行うのとは違い、X 軸と Y 軸に沿って(同時に)画像を圧縮するだけです。ここで重要なのは、絶対歪みマップに対して行ったことは何であれ、それを適用するどの画像の最終画像にも行われるということです。それが歪みマップの力です。

合成 'Distort' メソッド

ここまで、FX, 一般 DIY 演算子を使って絶対歪みマップを適用してきました。これは行っていることを正確に調整し細かく調節する手段を提供しますが、非常に遅くもあります。合成演算子 "Distort" は、上で使ってきたものと非常によく似た公式をエンコードしています。ただし、後で相対変位マップで見る "Displace" 合成演算子ともう少し互換性を持つように実装されています。

では、"Distort" 合成を使って、最後の「爆縮」の例を繰り返してみましょう。

  magick koala.gif  map_compress.gif map_compress_y.gif \
          -compose Distort  -define compose:args=37.5x37.5 -composite \
          distort_compose.gif

[IM Output] [IM Output] [IM Output] [IM Output]

上記での「Define 設定」 "compose:args" の使用に注目してください。この値は、使われる LUT グラデーションに対する乗数です(完全なグレーを中心とする)。使われている値 '37.5' は画像の幅と高さの半分(75 ピクセル)です。その乗数を変えて歪みの全体的なスケールを拡大または縮小できます。"compose:args" の値が定義されていない場合、正しい値がデフォルトとして使われます。値がゼロに設定されると、その方向には歪みが適用されません。合成引数を自動的に設定したい場合は、次の同等の Set "option:" メソッドを使ってそれを計算できます…… |

  magick koala.gif  map_compress.gif map_compress_y.gif \
          -set option:compose:args '%[fx:w/2]x%[fx:h/2]' \
          -compose Distort  -composite \
          distort_compose_set.gif

[IM Output]
あるいは、IM に正しい値を計算させるために未定義にします(2D Distort の場合)…… |

  magick koala.gif  map_compress.gif map_compress_y.gif \
          -compose Distort -define compose:args='' -composite \
          distort_compose_default.gif

[IM Output]

無変換歪みマップ

これ以上進む前に、少し戻って上記の「無変換(noop)」の例をもう一度見ておきたいと思います。これは実際には画像をわずかにぼかします。私が概説した公式が実は厳密には正確でないからです。元の画像の「無変換」コピーを得ることは、自分の歪みの数学が正しいかどうかの良いテストになります。

つまり、完璧なグラデーションが与えられたとき、ソース画像の各ピクセルを出力先画像にマッピングできます。すなわち、LUT の「白」(または 1.0)の値は、出力先の最も右(または最も下)のピクセルに正確にマッピングされます。

無変換歪みをテストするには、「ピクセルチェック画像」(例: "pattern:gray50")を使います。これはあらゆる歪みを、したがって適用された数学のあらゆる問題を浮かび上がらせるからです。では、これまで使ってきたメソッドに無変換歪みを適用してみましょう…… |

  magick -size 75x75 pattern:gray50 \
          \( gradient: -rotate 90 \) \( gradient: -flip \) \
          -fx 'p{u[1]*w,u[2]*h}'    distort_fx_check.gif

[IM Output]
|

  magick -size 75x75 pattern:gray50 \
          \( gradient: -rotate 90 \) \( gradient: -flip \) \
          -set option:compose:args '%[fx:w/2] x %[fx:h/2]' \
          -compose Distort  -composite  distort_compose_check.gif

[IM Output]
ご覧のように、両方のメソッドが「ピクセルチェック」画像の再現に失敗しました。ただし、座標の計算方法の違いにより、わずかに異なる形で失敗しました。何が起きたかというと、色のルックアップからピクセル座標へのスケーリング係数が 1 ピクセルだけずれているのです。これがなぜ起きたかの詳細については、歪み, 画像座標 vs ピクセル座標を参照してください。 | _FX 歪みは右上隅(ピクセル位置 0,0)を中心とし、下端と右端に沿って重複した仮想ピクセルを生成します。これは、ルックアップ色から画像座標へのスケーリングの中心を変えようとしないからです。そのため、スケーリングが間違っていても、黒いピクセルはピクセル 0,0 を中心としたままです。

合成 "Distort" 演算子は、スケーリングが適用される前にゼロが画像の中心に来るように座標を平行移動します。これは「変位マップ」(後述)のスケーリングの一部として行われます。そのため、不正確なスケーリングは各端に沿って画像の端を 1/2 ピクセル内側に引き込む一方、画像の中心は正しいままにします。_
---|---
ここに、絶対歪みマップ用の修正された「完璧な無変換」バージョンを示します。これは本質的に、色と座標の間のスケーリング係数を計算する際に画像座標(幅と高さを 1 だけ減らしたもの)を使います。 |

  magick -size 75x75 pattern:gray50 \
          \( gradient: -rotate 90 \) \( gradient: -flip \) \
          -fx 'p{u[1]*(w-1),u[2]*(h-1)}'    distort_fx_check_correct.gif

[IM Output]
|

  magick -size 75x75 pattern:gray50 \
          \( gradient: -rotate 90 \) \( gradient: -flip \) \
          -set option:compose:args '%[fx:(w-1)/2] x %[fx:(h-1)/2]' \
          -compose Distort  -composite  distort_compose_check_correct.gif

[IM Output]
実際のところ、"compose:args" のデフォルト値は、未定義の場合、正しいスケーリング値を使います。 |

  magick -size 75x75 pattern:gray50 \
          \( gradient: -rotate 90 \) \( gradient: -flip \) \
          -compose Distort -define compose:args='' -composite \
          distort_compose_default_check.gif

[IM Output]
ただし、これらのわずかな不正確さは、歪みを使う際には通常それほど重要ではないので、わずかな違いは一般に無視されることを指摘しておくべきでしょう。実際に問題になったときに知っておけるよう、心に留めておくだけにしてください。

歪みマップの問題点

回転を試みることで画像の歪みを続けましょう。これには回転したマップの生成が少々厄介になりますが、行うことはできます……

  magick -size 75x75 gradient: -background black -rotate 45 \
          -gravity center -crop 75x75+0+0 +repage  map_rot45_x.png
  magick map_rot45_x.png  -rotate 90              map_rot45_y.png
  magick koala.gif  map_rot45_x.png   map_rot45_y.png \
          -compose Distort  -composite    distort_rot45.gif

[IM Output] [IM Output] [IM Output] [IM Output]

これで任意の画像を回転させるもう一つの方法ができました。この技法の最大の問題は、回転を使って歪みマップを作成することで、対角線の端に沿って奇妙な色のピクセルが導入されてしまったことです。直前の例では、これにより画像の右下隅に沿った線にランダムなピクセルが追加されました。これらの「ランダムな」色は、「より良い」画像を生成するために回転が導入したアンチエイリアス値です。しかし歪みマップにとって、アンチエイリアスされた端のピクセルは本当に問題を引き起こしかねません。さて、回転した LUT 画像の端の色をより良く定義してみることができます。この場合、より大きなグラデーション画像を生成し、回転を正しいサイズに切り抜くことができます。

  magick -size 100x20 xc:white xc:black -size 115x75 gradient: \
          +swap -append   -rotate 45 \
          -gravity center -crop 75x75+0+0 +repage   map_rot45b_x.png
  magick map_rot45b_x.png  -rotate 90              map_rot45b_y.png
  magick koala.gif  map_rot45b_x.png   map_rot45b_y.png \
          -compose Distort  -composite     distort_rot45_better.png

[IM Output] [IM Output] [IM Output] [IM Output]

このように、LUT 内のすべてのピクセルがアンチエイリアスなしで適切に定義されました。これは今度はわずかに異なる問題を示します。最終画像のすべてのピクセルは適切に定義されていますが、一部のピクセルは最終画像の一部であるべきではありません。それらは結果の画像において実際の意味を持ちません。これは、LUT を使ってソース画像から取得する絶対座標を指定する際の最大の問題を表しています。これらの未定義領域で IM が何をすべきかを指定する方法がないのです。

マスクによる未定義ピクセルの設定

「未定義ピクセル」問題を解決するより一般的な方法は、歪みにおいて実際にどのピクセルが有効に定義された結果なのかのマップを定義することです。言い換えれば、マスキング画像です。たとえば……

  magick -size 75x75 xc:white -background black -rotate 45 \
          -gravity center -crop 75x75+0+0 +repage  map_rot45b_m.png
  magick distort_rot45_better.png map_rot45b_m.png \
          -alpha off -compose CopyOpacity -composite   distort_rot45_masked.png

[IM Output] [IM Output] [IM Output]

これで歪みマップに3つの画像が関わるようになり、結果は確かに複雑になってきました。もちろん、典型的な状況ではおそらくそこまでする必要はないでしょうが、一般的な場合には必要です。

統合歪み画像

しかし、3つのマップがすべてグレースケール画像であることにお気づきかもしれません。これは、すべてのマップを単一の歪みマップ画像に統合するのが十分理にかなっていることを意味します。たとえば、「X 歪みマップ」を 'red' チャンネルに、「Y マップ」を 'green' に、マスクを 'alpha' または透明度チャンネルにマッピングしてみましょう。これによって扱いやすくなります。

  magick map_rot45b_x.png map_rot45b_y.png \( map_rot45b_m.png -negate \) \
          -alpha off -channel RGA -background black -combine  map_rot45u.png

[IM Output] [IM Output] [IM Output] [IM Output]

| チャンネル統合画像の 'blue' チャンネルは定義されていないので、現在の "-background" 色から値を取ります。上記では 'black' すなわち値ゼロにあらかじめ設定しています。
---|---
では、この統合歪みマップをコアラ画像に適用してみましょう。これには残念ながら2つの画像処理ステップが必要です。一つは画像を歪めるため、もう一つは結果をマスクするためです。

  magick koala.gif -alpha set   map_rot45u.png \
          \( -clone 0,1  -fx 'p{v.r*w,v.g*h}' \
             +clone -compose Dst_In -composite \) -delete 0,1 \
          distort_rot45_unified.png

[IM Output] [IM Output] [IM Output]

統合歪みマップ画像を使って、「Distort」合成メソッドを直接使うこともできます…… |

  magick koala.gif -alpha set   map_rot45u.png \
          -compose Distort -define compose:args='' -composite \
          distort_rot45_compose.gif

[IM Output]
「統合歪みマップ」画像にはまだ未使用のチャンネル(blue)があります。その論理的な用途の一つは、歪んだ画像にハイライトとシャドウを追加する手段としてです。(オーバーレイハイライトを参照)。この技法をさらに一歩進めたものを、下記の球面歪みマップの例で見ることができます。

砂時計歪みマップ

さて、私は各行をその行の高さに応じて異なるように水平方向にスケーリングする1次元の歪みマップが欲しいと思いました。太った人を非常に痩せて見せる、本物のカーニバルのびっくりハウスの鏡のような歪みを生み出すようなものです。言い換えれば、一種の砂時計歪みです。これはかなり複雑な LUT 画像で、いろいろといじくり回した後、高さに応じて変化するが水平方向には線形なグラデーションマップを生成する次の式を思いつきました。 |

  magick -size 100x100 xc:  -channel G \
          -fx 'sc=.15; (i/w-.5)/(1+sc*cos(j*pi*2/h)-sc)+.5' \
          -separate  map_hourglass.png

[IM Output]
| グレースケールグラデーションを生成する際、上記の例の 'G' すなわち緑チャンネルのように、-fx 演算子に1つのカラーチャンネルだけを生成するよう求めるだけで、3倍高速にできます。このチャンネルはその後分離して、必要なグレースケール画像を形成できます。特に非常に複雑な "[-fx](https://imagemagick.org/command-line-options/#fx)" 式を使う場合、これは非常に大きな速度向上を表しえます。
---|---
'sc' は砂時計のスケーリング係数(値の範囲は 0 から 0.5)で、歪みの大きさを調整できます。では、このマップを組み込みの "rose:" 画像に適用してみましょう。100x100 ピクセルのマップが 70x46 ピクセルの画像と一致しないことに注意してください。これは事態を複雑にします。与えた歪みマップに合わせるためにソース画像内の現在のピクセルを適切な量だけスケーリングして、そのピクセルの色の位置をルックアップする必要があるからです。 |

  magick rose:  map_hourglass.png \
          -fx 'p{ v.p{i*v.w/w,j*v.h/h}*w,  j}'  distort_hourglass.png

[IM Output]
これを注意深く見ると、ピクセルの X 座標 'i' に歪みマップ画像の幅 'v.w' が掛けられ、元の画像の幅 'w' で割られて 'i*v.w/w' を生成しています。同じことがピクセルの Y 座標 'j*v.h/h' でも起こります。これは出力先画像内のピクセル座標を歪み LUT 画像に合わせて再スケーリングします。ルックアップされた座標はその後、LUT 値にソース画像の幅を掛けることでスケーリングされ、色のルックアップのための X 座標になります。X と Y の両方の歪みマップがある場合は、Y マップについてもスケーリングされたルックアップを繰り返す必要があります。もちろん以前見たのと同じ「端」の歪みがあるので、仮想ピクセル設定を透明に変更してみましょう。 |

  magick rose: -alpha set  -virtual-pixel transparent -channel RGBA \
          map_hourglass.png  -fx 'p{ v.p{i*v.w/w,j*v.h/h}.g*w, j}' \
          distort_hourglass2.png

[IM Output]
"-channel" 設定の使用に注目してください。これは "[-fx](https://imagemagick.org/command-line-options/#fx)" がソース画像からアルファチャンネル(透明)の値を扱い返すことを保証します。具体的には透明な仮想ピクセルです。また、歪みマップをルックアップする際、緑チャンネルからのみルックアップした('v.p{}.g' を使用)ことにも注目してください。これを行わないと、ソース画像から処理されているのと同じチャンネルが使われ、マップでは「alpha」が定義されていません。この歪みマップは、画像が長方形のままになるよう非線形グラデーションを使って、中央より端により多くの歪みを与え、より「丸み」または「円筒形」の見た目にすることで、さらに良くできます。誰かこれをやってみたい人は? メールをください

球面歪みマップ

前の砂時計歪みマップの例では、コサインカーブによって水平方向にスケーリングされたグラデーションを生成しました。もう少し手を加えると、代わりに球状の形を生成できます…… |

  magick -size 100x100 xc:  -channel R \
          -fx 'yy=(j+.5)/h-.5; (i/w-.5)/(sqrt(1-4*yy^2))+.5' \
          -separate  +channel     sphere_lut.png

[IM Output]
ただし、上記は厳密には正確ではないことに注意してください。圧縮されたグラデーションは線形グラデーションのままで、円内に収まるように圧縮されただけです。より正確な表現には、おそらく非線形グラデーションの作成が必要でしょう。それは絶対位置の観点では 'arccos()' 関数になります。さて、このマッピングには無効と分類される大きな領域もあるので、最終画像でどのピクセルが有効で無効になるかを定義する何らかのマスキングが必要です。この場合は単純な円で十分です。 |

  magick -size 100x100 xc:black -fill white \
          -draw 'circle 49.5,49.5 49.5,0'    sphere_mask.png

[IM Output]
そして仕上げに、オーバーレイハイライトで開発したような陰影ハイライトも必要です。Overlay または Hardlight 合成で使うためのものです…… |

  magick sphere_mask.png \
          \( +clone -blur 0x20 -shade 110x21.7 -contrast-stretch 0% \
             +sigmoidal-contrast 6x50% -fill grey50 -colorize 10%  \) \
          -composite sphere_overlay.png

[IM Output]
上記の陰影は球オブジェクトの境界内でのみ意味を持つことを覚えておいてください。だから陰影が境界からはみ出ても重要ではありません。実は、もっと良い球状の陰影を考え出して、もっと良いボール状の画像を生み出してみたいなら、ぜひ見てみたいです。では、3つの画像すべて、X 座標 LUT、オーバーレイ陰影、透明度マスクを、(簡単のため)適切なサイズの実際の画像に適用してみましょう。

  magick lena_orig.png -resize 100x100   sphere_lut.png   -fx 'p{ v*w, j }' \
          sphere_overlay.png   -compose HardLight  -composite \
          sphere_mask.png -alpha off -compose CopyOpacity -composite \
          sphere_lena.png

[IM Output] [IM Output]

この特定の例は、絶対歪みマップの最も強力な側面を示しています。任意の自由形オブジェクト上に(必ずしも数学的にではなく)グラデーションを定義できるので、それが曲線、しわ、折り目などであっても、任意の画像をそのオブジェクト上にマッピングできます。簡単に言えば、いったんオブジェクトのマッピングを練り上げれば、任意の画像をその表面上にマッピングできます。そして、よりリアルに見せるために、2つ目のマッピングをオーバーレイして、ハイライト、シャドウ、エッジ、その他の特徴を追加できます。もちろん3つの画像はすべてグレースケールなので、保管が簡単になるよう、単一の統合歪みマップ画像にまとめることができます。この場合は、X 座標の歪み LUT を Y 座標にも再利用することで、より球状の歪みにします。 |

  magick sphere_lut.png   \( +clone -transpose \) \
          sphere_overlay.png   \( sphere_mask.png -negate \) \
          -channel RGBA  -combine    spherical_unified.png

[IM Output]
かなりきれいなマップです。でも、それを解釈しようとするなら、覚えておいてください: 「red」と「green」チャンネルは X と Y 座標 LUT、「blue」はハイライトとシャドウ効果のオーバーレイ、透明度チャンネルは最終画像用の無効ピクセルマスクを保持しています。では、「Distort」合成メソッドを使ってそれを適用してみましょう。

  magick mandrill_grid_sm.jpg   spherical_unified.png  \
          \( -clone 0,1 -alpha set -compose Distort -composite \) \
          \( -clone 1   -channel B -separate +channel \) \
          \( -clone 2,3 -compose HardLight -composite \) \
          \( -clone 4,1 -compose DstIn -composite \) \
          -delete 0--2  spherical_mandrill.png

[IM Output] [IM Output]

順に……

  • 歪みマップを適用する(マスクを含む)
  • 統合画像マップから陰影マップを抽出する
  • 陰影マップを歪んだ画像に適用する
  • 陰影操作で失われたマスクを復元する
  • 最終画像以外をすべて削除して保存する

この複雑さは、純粋に陰影マスクを抽出し、陰影が削除したアルファマスクを復元する必要があるためです。

円弧歪みマップ

位置歪みマップを使って実際に何が可能かを示すために、上記の'Arc' 歪みメソッドが提供するものに似た絶対歪み LUT をここに示します。基本的に、歪められる各画像の各ピクセルについて座標マッピングを計算するのではなく、それらの計算済み座標を2つの X と Y 座標のグレースケール LUT マップに保存します。つまり、歪み全体をより単純なルックアップテーブル画像にあらかじめ計算しておき、それ以上の平方根や三角関数を必要とせずに、何度も何度も何度も適用できるようにします。

  magick -pointsize 30 -font Candice label:Anthony -trim +repage \
          -gravity center -resize 95x95 -crop 100x100+0+0\! \
          -flatten text_image.jpg
  magick -size 100x100 xc: -channel G  -fx 'atan(j/(i+.5))*2/pi' \
          -separate   -flip -flop       map_p_angle.png
  magick -size 100x100 xc: -channel G  -fx '1-hypot(i,j)/(w*1.6)' \
          -separate   -transverse       map_p_radius.png
  magick text_image.jpg   map_p_angle.png map_p_radius.png \
              -fx 'p{u[1]*w,u[2]*h}'    distort_p_curved.jpg

[IM Output]
カラーソース |
| [IM Output]
角度 - X マップ |
| [IM Output]
半径 - Y マップ |
| [IM Output]
曲げられたテキスト
---|---|---|---|---|---|---

もちろんその歪みマップを生成するのは難しかったですが、いったん("Gimp" のような画像エディタを使って芸術的にでも、好きな方法で)一度それが行われれば、膨大な数の画像に再利用できます。

極座標歪みマップ

物事を正しく機能させるために、出力先画像をソース画像ではなく歪みマップによって定義する必要がある場合もあります。たとえば、テキストを円にマッピングしたい場合(極座標変換とも呼ばれます)、高さの3~4倍の長さの画像(高アスペクト比)を使えるようにする必要があり、そうしないと結果はあまり読みやすくなりません。それを行うには、最初の(X マップ)画像が入力ソース画像ではなく最終結果のサイズを設定するために使われるよう、歪みマップ画像をカラーソース画像の前に置きます。

  magick -size 100x100 xc:  -channel G \
          -fx 'atan2(i-w/2,h/2-j)/pi/2 + .5' \
          -separate  map_p_angular.png
  magick -size 100x100 xc:  -channel G \
          -fx 'rr=hypot(i-w/2,j-h/2); (.5-rr/70)*1.2+.5' \
          -separate  map_p_radial.png
  magick -font Candice -gravity center -size 200x50 \
                                label:'Around  the  World'    text.jpg
  magick map_p_angular.png map_p_radial.png text.jpg \
                 -fx 'u[2].p{ u*u[2].w, v*u[2].h }' distort_p_circle.jpg

[IM Output]
角度方向 - X マップ |
| [IM Output]
半径方向 - Y マップ |
| [IM Output]
カラーソース |
| [IM Output]
円形のテキスト
---|---|---|---|---|---|---

本質的に、カラーソース画像は今や任意のサイズやアスペクト比にでき、物事は正しく扱われます。ただし、ソース画像のアスペクト比を正しく扱うために歪みマップの生成を調整する必要があるかもしれません。上記のマップを生成する際、値 '70' は中線が置かれる円の最終的なサイズを制御します。一方 '1.2' の値は、画像を円に入れる際の垂直方向のスケーリングを制御し、歪んだテキストの高さを調整できます。 この "-fx" 式は歪みマップを最初に与え、カラーソースを3番目(インデックス 2)の画像として与えることを要求することを覚えておいてください。ただし、これはソース画像に保存されたメタデータも失われることを意味します。
_この歪みマップの問題は、「X マップ」に非常に鋭い色の不連続があることです(数学における漸近線によって引き起こされます)。この線は、より大きな画像を生成するために何らかの色のルックアップやマップのリサイズを行うとき、鋭いままでなければなりません。つまり、このマップの何らかのリサイズや補間ルックアップが、その漸近線に沿ってグレーのルックアップ色を生成しないようにする必要があります。

この線に沿ってグレーのルックアップを生成してしまうと、最終結果に色付きピクセルの線(画像の中央からルックアップされたもの)ができてしまいます。

このため、この歪みマップは常に最終画像に必要なサイズで生成し、これまで示したスケーリング技法を決して使わないことが推奨されます。_
---|---
これを他の効果にも使えます。たとえば円形のチェッカーボードなど…… |

  magick map_p_angular.png map_p_radial.png \
          -size 150x90 pattern:checkerboard \
          -fx 'u[2].p{ u*u[2].w, v*u[2].h }'   distort_check_circle.gif

[IM Output]
他の興味深い効果のために、IM が提供する上記のような他の組み込みパターンのいくつかを試してみてください。 | _上記は "-fx" を使った画像歪みの限界をはっきりと示しています。画像の中央付近では、放射状の線がエイリアスを起こしています。大きな領域を単一のピクセルへとピクセル統合することが行われないからです。一方、画像の端、特に隅では、放射状の線が適切にぼかされています。

原因は、"-fx"(および大半の古い歪みメソッド)が、ソース画像の色の単純な非スケーリング補間ルックアップしか行わないことです。これは、画像がより小さくスケーリングされるとき、ソース画像のピクセルが統合されて出力先ピクセルの正しい色を生成しないことを意味します。

これは拡大される領域(隅のような)には問題ではなく、極端な圧縮(中央)の場合だけです。そのため、一つの解決策はスーパーサンプリングの使用ですが、これがするのは問題をより高いレベルの圧縮へと先延ばしにすることだけです。_
---|---
| _歪みマップ内の同じ漸近線(突然の変化)(画像の中央から下まで)は、上記の例でもその線に沿って鋭い色の変化を生み出します。その線を、他の放射状の線(中央から上までのような)と比較してみてください。それらは前述の補間ルックアップにより画像の端に近づくにつれて非常にぼやけてきます。

これは、タイル化可能な画像で円形パターンを生成する際(上記のような)に問題になりかねず、画像のその部分での目に見える違いを避けるための特別な扱いが必要になるかもしれません。

これを避けるには、漸近領域を避けるために、画像の上半分を下半分とは別に歪めるほうが良いかもしれません。

_
---|---

行のシャッフル

この例では、もう少し変わったことをします……画像の行をランダムにシャッフルするのです。まず、X 用にグラデーション(赤チャンネル)、Y 用にランダムノイズ画像(緑チャンネル)を持つマップを作成します。

  magick rose: \
          \( -size 46x70 gradient: -rotate -90 \) \
          \( -size 1x46 gradient: -spread 23 -scale 70x46\! \) \
          -compose Distort -define compose:args='' -composite \
          rose_row_shuffle.png

[IM Output] [IM Output]

残念ながら "-spread" は、スワップするピクセルの選択に仮想ピクセルを含めているようで、一部の行が重複し、他の行が完全に失われてしまいます。言い換えれば、「シャッフル」画像マップが完全には正しくないのです。ピクセルをシャッフルするより良い解決策をお持ちですか?


相対ルックアップ変位マップ

ご覧のように、絶対歪みマップはかなり簡単に作成し使えます。しかし、歪みに「未定義」の領域がある場合や、歪みがソース画像の通常の境界の「外側」に出る領域がある場合に深刻な問題があります。より深刻な問題は、常にグラデーションを扱っていることで、それが色のルックアップの絶対座標を定義します。マッピング画像のどの部分も単純でも、きれいでも、手で変更や編集が簡単でもありません。その作成と使用には特別な技法と数学が必要です。それは一般に「芸術的」な展開がほとんど関与しないことを意味します。しかし、最終的な色を取得する座標を指定する、ルックアップテーブルを使う別の方法があります。相対変位マップを使うことです。「マップ」がソース画像から各ピクセルの色をルックアップする正確な座標を定義するのではなく、代わりに現在位置に対するオフセットすなわち_変位_を定義します。さて、オフセットは正の値にも負の値にもなりえ、負の値は色値にエンコードするのに少々トリックが必要です。そこで彼らがするのは、「純粋なグレー」を座標の 0 変位(変化なし)と定義することです。次に「黒」を最大の負の変位、「白」を最大の正の変位を意味するようにします。これは説明が難しいので、例を見てみましょう。まず「変位させる」テスト画像を作成します。 |

  magick -font Candice -gravity center -size 150x50 \
                                           label:'Anthony'    label.jpg

[IM Output]
さて、ちょっとした「魔法(magick)」を使って、「純粋な白」と「純粋な黒」の領域を持つ「純粋なグレー」画像を作成します。 |

  echo "P2 5 1 255\n 127 0 127 255 127" |\
                magick - -scale 150x50\! -alpha off   displace_map.jpg

[IM Output]
さて、この画像を「変位マップ」として使うには、変位マップから「グレー値」を取得し、それを X 座標と Y 座標のどちらか(または両方)に加えます。つまり、変位マップの「グレーさ」に応じて、現在位置からの相対量だけルックアップを変位させます。「値」は特別な方法で扱われ、「純粋なグレー」はルックアップ点(この場合は Y 座標のみ)のゼロ変位を意味しますが、「白」(正)または「黒」(負)の値には「最大変位」が使われます。たとえば、変位マップを私たちの「label」画像に適用してみましょう。 |

  magick label.jpg  displace_map.jpg  -virtual-pixel Gray \
          -fx 'dy=10*(2*v-1); p{i,j+dy}'   displaced.jpg

[IM Output]
ご覧のように、画像のさまざまな部分が変位マップの色に応じて「動いた」ように見えます。「白」の領域は与えられた「変位値」をルックアップ点に加えるので、その領域では各ピクセルがソース画像を「10」ピクセル「南方向」(正の Y 方向)にルックアップします。結果として、ソース画像が上方向に動いたように見えます。動いたのはルックアップであって、実際の画像そのものではないことを覚えておいてください。だから白では上方向、つまり負の方向に動いて見えたのです。「黒」の変位を持つ領域でも同様の効果が見られました。ソース画像が下方向に動いたように見えました。ルックアップの変位が負の方向に行われたからです。よく考えてみてください。「変位したルックアップ」が実際には通常の画像境界を越えてルックアップできることにも気づくでしょう。これにより、仮想ピクセル設定を使ってこれらの境界外のピクセルを制御できます。上記では、グレーのピクセルを返すよう要求しただけです。上記の例の「最大変位」値 '10' は非常に重要で、マッピング画像の「純粋な白」または「純粋な黒」の変位値に対して、ソース画像のどの部分が動いて見える最大の相対距離です。ルックアップ、したがって入力画像をこの値より遠くに変位させることはできません。最大の白または黒の値と中央の無変位の 50% グレー値の間の他のグレーの濃淡は、ルックアップを適切な量だけ変位させます。そのため、25% グレー値はルックアップを変位値の 1/2 だけ負の方向に変位させ、75% グレーは正の方向にその値の 1/2 だけ変位させます。この値は、絶対歪みマップ相対変位マップの主要な違いです。変位マップをまったく変更することなく、変位値を変えるだけで、相対変位を増減させ、画像をより歪めたり歪めなくしたりできます。また、「ゼロ変位」マップは単なる単色の 50% すなわち純粋なグレーであり、複雑なグラデーションではないので、単純なグレー画像から始めて、芸術的に領域を明るくしたり暗くしたりして、望みの変位を生成できます。これは、複雑で正確な数式を必要とせず、単に形や領域を描くだけで行えます。そして最後に、すべての変位が相対的なので、端効果によって生み出されるような乱暴な値が乱暴またはランダムなピクセル色を生み出すことがありません。実際、後で見るように、変位マップを滑らかにしたりぼかしたりすることは、上記の例で見られるような不連続な「切れ目」効果を取り除くので、実は良いことなのです。まとめると 変位マップははるかに制御しやすく芸術的で、複雑で正確な数学を必要とせず局所的な変位を提供し、ミス、端効果、あるいは変位マップのぼかしに対しても非常に寛容です。水、波、歪む鏡、光の屈曲、レンズのような効果、すりガラスや泡ガラスのような効果を生成する場合のような単純な「変位」型の歪みに理想的です。一方、「極座標」、回転、「透視」歪みのような高度に数学的な歪みや、その他の現実世界の 3D 型マッピングは、簡単には実現できません。とはいえ、それが不可能というわけではなく、後で見るように2つのスタイルのマップの間を実際に変換できますが、より難しいだけです。

合成変位メソッド

実際に何が行われているかを見られるように、変位マッピングを行うのに DIY FX 演算子を使ってきました。しかしそれは遅い技法です。でも、同等の組み込みの合成演算子 "Displace" があります。その使い方は次の通りです……

    magick {_画像_} {_変位マップ_} \
            -compose Displace   -define compose:args={_X_}x{_Y_} \
            -composite   {_結果_ +}

    magick {_画像_} {_変位マップ_} \
            -compose Displace   -set option:compose:args {_X_}x{_Y_} \
            -composite   {_結果_ +}

    magick composite {_変位マップ_} {_画像_} \
              -displace {_X_}x{_Y_}    {_結果_ +}

順序、特に "magick composite" コマンドでの順序に注意してください。

define の代わりに "-set" を使うと、引数にパーセントエスケープを使えるようにもなります。'X ' と 'Y ' の値は、与えられた変位マップ内の「白」と「黒」の色に使われる方向と「最大変位」を定義します。一方または両方の値を定義できるので、任意の特定の方向に変位させることができます。つまり、通常、変位マップは、'X ' と 'Y ' の値によって制御される最大強度を持つ、何らかのランダムな方向への線形変位を提供します。「マップ画像」は次に、その最大値のどれだけが、負の最大値(黒)から正の最大値(白)まで適用されるかを設定し、完璧なグレーはそのピクセルのルックアップの無変位を意味します。たとえば、上で扱ったのと同じ Y 変位の例がここにあります…… |

  magick label.jpg  displace_map.jpg  -virtual-pixel Gray \
          -compose Displace -define compose:args=0x10 -composite \
          displaced_y.jpg

[IM Output]
"[-geometry](https://imagemagick.org/command-line-options/#geometry)" や "[-gravity](https://imagemagick.org/command-line-options/#gravity)" 設定のような他の設定を使って、変位マップが画像上に重ねられる領域を調整することもできます。変位マップによるピクセルのルックアップは、重ねられた画像の部分の外側の領域を参照でき、それらを重ねられた領域に複製することもできます。

単純な変位の例

滑らかな遷移のない生の色の領域からなる変位マップは、上で見たように、結果の画像内の異なる領域の間で一般に不連続な変位を生み出します。実際、この技法を使って、ひびの入った鏡を覗き込んでいるかのように「割れる」変位マップを生成できます。たとえば、下記の割れた鏡を参照してください。色が一つの領域から別の領域へ滑らかに流れれば、より良く滑らかな結果を生み出せます。たとえば、変位マップをぼかすことで、変位した領域の間に波のような遷移を生成します…… |

  magick displace_map.jpg  -blur 0x10   dismap_wave.jpg
  magick label.jpg  dismap_wave.jpg  -virtual-pixel Gray \
          -compose Displace -define compose:args=0x10 -composite \
          displaced_wave_y.jpg

[IM Output]
[IM Output]
画像を Y 方向に変位させる代わりに、マップを使って画像を X 方向に変位させ、一種の圧縮波を生み出すこともできます。 |

  magick label.jpg  dismap_wave.jpg  -virtual-pixel Gray \
          -compose Displace -define compose:args=10x0 -composite \
          displaced_wave_x.jpg

[IM Output]
同じ変位マップを X と Y の両方向に使うことで、圧縮波と振幅波の両方を加えられます。 |

  magick label.jpg  dismap_wave.jpg  -virtual-pixel Gray \
          -compose Displace -define compose:args=10x10 -composite \
          displaced_wave_xy.jpg

[IM Output]
画像はまだ単一の線形方向に変位しているので、上記の画像は下り坂で引き伸ばされ、上り坂で圧縮されている点に注意してください。つまり、歪みは角度すなわち「ベクトル」で、水平成分と垂直成分の両方を持って行われています。この効果がまるで水中のように見えるのがわかるでしょう。水面の穏やかな波紋によって画像が歪められているのです。しかし、変位マップは、反射または屈折した画像でできるのと同じように、元の画像の複数のコピーを含むことができます…… |

  echo "P2 3 1 255\n 255 127 0 " | magick - -scale 150x50\! dismap_copy.jpg
  magick label.jpg  dismap_copy.jpg \
          -compose Displace -define compose:args=66x0 -composite \
          displaced_copy.jpg

[IM Output]
[IM Output]
グラデーションを使って、画像の一部の鏡像反転(flip や flop)を作成することもできます。たとえば、ここでは線形変位マップを使って、画像の片側から反対側へピクセルをコピーできます。 |

  magick -size 50x150 gradient: -rotate -90  -alpha off  dismap_mirror.png
  magick label.jpg  dismap_mirror.png \
          -compose Displace -define compose:args=150x0 -composite \
          displaced_mirror.jpg

[IM Output]
[IM Output]
この変位マップがどう機能するかわかりますか? ヒントとして、最も左と最も右の端がどんな変位を持つかを割り出し、それから残りの画像がそれにどう収まるかを見てください。ただし、ここでもグラデーション画像を使っているので、変位マップの単純さは失われます。そのため、鏡像は画像に対して直接Flip 操作を使うか、代わりに絶対歪みマップを使うほうが良いでしょう。グラデーションを反転させると画像が縮小されることに注意してください。 |

  magick -size 50x150 gradient: -rotate 90  -alpha off  dismap_shrink.png
  magick label.jpg  dismap_shrink.png \
          -compose Displace -define compose:args=150x0 -composite \
          displaced_shrink.jpg

[IM Output]
[IM Output]
上記はまた、変位マップが持つ特定の問題も示しています。画像のある領域(または全体)が 50% を超えて圧縮されると、エイリアスのアーティファクトを生成し始めます。これは、はっきりと見える階段状の「エイリアス」エッジに特に顕著です。前に述べたように、これに対する一つの解決策は、各出力ピクセルを生成するために使われるピクセル数をスーパーサンプリングすることです。それを行うには、画像と変位マップの両方を拡大し、結果の画像をより通常のサイズに戻します。これにより、より多くのピクセルが結果の特定のピクセルの設定に参加でき、より良い画像を生成できます。たとえば…… |

  magick label.jpg  dismap_shrink.png  -resize 200% \
          -compose Displace -define compose:args=400x0 -composite \
          -resize 50%    displaced_resize.jpg

[IM Output]
はるかに良く滑らかな結果ですが、おそらく少々ぼやけてもいます。 グラデーションのグラフ化 上記の例から直接生まれたのは、単純な線の Y 変位を使うことで、変位マップの色のグラフを生成できるというアイデアでした。たとえば、ここでは数学的な sinc() 関数('sin(x)/x' として定義される)を生成し、そのグラデーションを変位マップとして使うことでグラフ化します……

  magick -size 121x100 xc: -fx 'sin(i*24/w-12)/(i*24/w-12)/1.3+.2' \
                                                      gradient_sinc.gif
  magick -size 121x100 xc: -draw 'line 0,50 120,50'     graph_source.gif
  magick graph_source.gif gradient_sinc.gif \
          -compose Displace -define compose:args=0x49 -composite \
          displace_graph.gif

[IM Output] [IM Output] [IM Output]

ご覧のように機能しますが、数学的なプロットには使いたくないですね。きちんとしたグラフ作成パッケージを使うほうが良いでしょう。しかしこの技法は、画像内のある行または列のピクセルの強度をプロットする手軽な方法として有用です。それがするのは、変位の大きな差がいかに簡単に不連続または滑らかでない結果を生み出すかを示すことです。基本的に「グラフソース」内の各ピクセルは平均化なしに一度に一つずつしか見られないので、あるピクセルから次のピクセルへの変位したルックアップの大きな差が、結果に大きな色変化を生み出しえます。教訓は、変位は滑らかな変位マップだけでなく、大きな領域や色の濃淡を含む変位画像でも最もうまく機能するということです。鋭く細い線にはあまりうまく機能しません。もちろん、ここでも歪みマップをスーパーサンプリングすることで改善できます…… |

  magick graph_source.gif gradient_sinc.gif  -resize 400% \
          -compose Displace -define compose:args=0x196 -composite \
          -resize 25%   displace_graph_2.gif

[IM Output]
結果ははるかに良くなりますが、グラフ作成パッケージで達成できるものほどには良くありません。それでも、その作成には ImageMagick だけが使われました。ここに同じグラフの別のバージョンがありますが、今回は単色を使っており、細い線を変位させるよりはるかにうまく機能します。 |

  magick -size 121x50 xc:white xc:black -append \
          gradient_sinc.gif  -resize 400% \
          -compose Displace -define compose:args=0x196 -composite \
          -resize 25%   displace_graph_3.gif

[IM Output]

領域の変位(線形)

もっと論理的な変位の問題を試してみましょう。画像のある領域をある位置から別の位置へ直線的に動かすことです。見てきたように「純粋なグレー」画像はいかなる変位も生じませんが、「白」の色はソース画像から正のルックアップ変位を生じます。たとえば、そのような画像を作成してみましょう…… |

  magick -size 75x75 xc:gray50 -fill white \
          -draw 'circle 37,37 37,20'  dismap_spot.jpg

[IM Output]
さて、この画像を適用すると、マークされた領域の内容には、与えられた変位値の方向に現れるものは何でもそのコピーが含まれるはずです。では、変位値 X +10 と Y +10 すなわち '10x10' を試してみましょう……

  magick koala.gif dismap_spot.jpg \
          -compose Displace -define compose:args=10x10 -composite \
          displace_spot.png

[IM Output] [IM Output] [IM Output]

ご覧のように、マークされた領域の内容には今や +10,+10 ピクセル南東にあった画像のコピーが含まれています。基本的にコアラの「尾」の画像です。言い換えれば、円内では画像が北東すなわち -10,-10 ピクセル変位しました。変位はルックアップのものなので、逆ピクセルマッピングによってソース画像は負の量だけシフトすることを覚えておいてください。画像は逆方向に変位するのです! また、動くのはマークされた領域内の画像であることにも注意してください。マークされた画像を変位させているのではなく、画像をマークされた領域_の中へ_変位させているのです。そして最後に、円の端での鋭い不連続に注意してください。マークされた領域内の領域は動かされ、外側の領域はまさにそのままです。これらは事実なので、繰り返す価値があります。

変位は値とは逆の方向に画像を動かす。
グレーでないマークされた領域だけが変位される。
鋭い色の変化は鋭い画像の不連続を生み出す。

では、もっと実用的なことを試してみましょう。'32,22' にあるコアラの鼻と目の間の中心を、'37,37' にある白(完全な正の変位)の円の中心へ動かしましょう。それには '-5,-15' の変位値が必要です(逆方向であることを覚えておいてください)…… |

  magick koala.gif dismap_spot.jpg \
          -compose Displace -define compose:args=-5x-15 -composite \
          displace_head.png

[IM Output]
これでコアラの頭の中央部分のきれいに中心に置かれたコピーができました。しかし画像はまだ「不連続」で、負の値を使うのはあまり良くありません。解決策は、代わりに黒い点を使うことですが、その点の端をぼかすことでもあります。また、コアラの頭をもっと多く包含するように大きくしましょう。というわけで、これが「正の動きの点」画像です…… |

  magick -size 75x75 xc:gray50 -fill black \
          -draw 'circle 37,37 37,17'  -blur 0x5  dismap_area.jpg

[IM Output]
画像をぼかしすぎないようにしてください。さもないと点の中央がもはや平らな黒い色でなくなります。代わりに、描かれた領域が黒で周囲の部分が完璧なグレーになるよう、画像をNormalize逆 Level 調整するだけでもよいです。後の例でこれが多く行われるのを見るでしょう。では、黒い「ぼやけた点」変位マップを使って、最後の「頭」の変位を繰り返しましょう。 |

  magick koala.gif dismap_area.jpg \
          -compose Displace -define compose:args=5x15 -composite \
          displace_area.png

[IM Output]
ご覧のように画像を「ぼやけた」領域へ +5,+15 動かしましたが、今回は領域の境界がより滑らかで、画像の残りの部分とつながっています。もちろん円の端にある耳はぼやけた端によって歪み、コアラの体も圧縮されましたが、それでも以前持っていたものよりずっと良いです。後続側で見える画像の「裂け目」を防いだり、変位した部分のコピーが残ったりするのを防ぐには、その点を広げるか、より複雑なグラデーション型の変位画像を作るとよいです。たとえば、コアラの頭を '32,22' の開始位置から画像の中央 '37,37' へ、すなわち +5,+15 ピクセル動かしたいが、画像全体をこの変化に合わせて調整して、はるかに滑らかな効果を出したいとします。これを行うには、'37,37' で黒の最大変位(正の画像変位)を +5,+15 の値で変位させたいでしょう。しかし、隅を 50% グレーで「固定」することで、画像の残りの部分が無傷のままになるようにもしたいでしょう。それには、Shepard's 補間スパースグラデーションがぴったりです。

  magick -size 75x75 xc:  -sparse-color  Shepards \
          '37,37 black   0,0 gray50  74,74 gray50  0,74 gray50  74,0 gray50' \
          dismap_move.jpg
  magick koala.gif dismap_move.jpg \
          -compose Displace -define compose:args=5x15 -composite \
          displace_move.png

[IM Output] [IM Output] [IM Output]

ご覧のように、画像全体に広がるより大きな変位の領域が得られます。結果は、以前使ったより狭い「点」メソッドよりもはるかに滑らかに変化する画像です。これは実はShepard's 歪みとちょうど同等ですが、移動する制御点が一つだけの場合に限ります。これは、Fred Weinhaus のスクリプト '[shapemorph](http://www.fmwconcepts.com/imagemagick/shapemorph/)' で使われているのとまったく同じメソッドですが、アニメーション付きです。まとめると: 小さな局所的な変位には「ぼかした点」変位を使えます。しかし、より長い距離にわたるより大きな変位には、ソース画像が裂けたり複製されたりするのを防ぐために、より大きな滑らかなグラデーション変位マップを使うべきです。

工事中

単純な変位モーフィング

変位ベクトルのサイズの変更


2画像モーフィング


ランダムな 1D 変位

波立つ水面の反射

前に述べたように、変位マップは水やガラスのような歪みを生成するのに特に有用です。[IM Output] この例では、花の画像を切り抜くことで小さな画像を生成しました。さて、これが波立つ水面の上に置かれているように見せたいと思います。波紋を生成するには、同じサイズのサイン波グラデーションが必要で、これは Evaluate Sin 関数を使って生成できます。数字 '8' はグラデーションに追加される「波」の数を表します。 |

  magick -size 150x80 gradient:  -evaluate sin 8  wave_gradient.png

[IM Output]
さて、より強調を与えるために、単純な垂直または水平の歪みではなく、角度のついた変位ベクトルを使ってその画像を歪めてみましょう。 |

  magick composite wave_gradient.png  flower.jpg -displace 5x5 flower_waves.png

[IM Output]
さて、それはあまり面白そうに見えませんが、その画像を反転させ垂直方向に圧縮して元の画像に追加したらどうでしょう…… |

  magick flower_waves.png -flip \
          flower.jpg  +swap -append  flower_waves_2.png

[IM Output]
残念ながら、それでもかなり人工的に見えます。理由は、反射が画像の上部と下部で同じに見えるからです。「奥行き」の感覚がありません。反射は元の画像と同じ明るさでもありますが、それはめったにない場合です。よりリアルにするには、強度が変化する波紋パターンを使う必要があります。次のものは、上で使っていた波グラデーションを「減衰」させるために、凝ったグラデーション数学を使います。つまり、上から下へ進むにつれて波パターンを線形に小さくしました。このトリックは、波が画像の下部(後で反転される)で純粋なグレーすなわち「無変位」の色で終わることを保証します。 |

  magick -size 150x80 gradient: \
          \( wave_gradient.png \
             +clone -compose multiply -composite \) \
          \( -clone 0 -negate -evaluate divide 2 \
             -clone 1 -compose plus -composite \) \
          -delete 0-1      waves_decreasing.png

[IM Output]
では、このグラデーションを適用して、花の新しい反射を形成しましょう。また、水自体に光がいくらか失われることを表すために反射画像を少し暗くし、より水の反射のように見せました。 |

  magick flower.jpg  waves_decreasing.png  \
          -compose Displace -define compose:args=8x8 -composite \
          -flip   +level 0,80% \
          flower.jpg  +swap -append   flower_in_water.png

[IM Output]
歪んだ画像が反射を形成するために反転されることに注意してください。また、画像は元の画像と接合する箇所に最も近い「水」の上部のほうが、下部よりも「波紋」が少なくなります。これは歪みに見る者からの距離の感覚を与えます。波の変位マップをわずかな回転、円弧、あるいは単に「ランダムな」変位で歪めることで、さらにリアルにできます。これは波により自然な見た目を与えます。ただし、「奥行き」が後で追加されるよう、「減衰」される前に行うほうが良いです。試して、実験して、思いついたものを教えてください。

将来のアニメーション波紋 -
  位相を変えながら -function Sinusoid を使う

2次元変位マッピング

ここまで、すべての相対変位マップは画像を一方向のみに変位させてきました。ただし、その方向は適切な '_X_ x _Y_' の変位値すなわち「ベクトル」を設定することで、望みの任意の角度に設定できます。しかし、2つの別々の変位を使うことで、画像が任意の方向に任意の量だけ変位する、はるかに複雑な変位を生み出せます。これを行うには、X と Y の方向それぞれに一つずつ、2つの変位マップを作成する必要があります。使えるコマンドは次の通りです……

magick {_画像_} {_X 変位_} {_Y 変位_} \
        -compose Displace   -define compose:args={_X_}x{_Y_} \
        -composite   {_結果_ +}

magick {_画像_} {_X 変位_} {_Y 変位_} \
        -compose Displace   -set option:compose:args {_X_}x{_Y_} \
        -composite   {_結果_ +}

composite {_X 変位_} {_画像_} {_Y 変位_} \
          -displace {_X_}x{_Y_}    {_結果_ +}

"magick composite" コマンドでの入力画像の順序に注意してください。この奇妙な順序は、"magick composite" のオプション処理を悪用する必要性と、歴史的な理由によって生じています。これを正しく行うことが極めて重要です。このため、"magick composite" ではなく "magick" コマンドを使うことをお勧めします。 IM v6.4.4 より前では、別々の X と Y の変位に2つの別々の変位マップを使うのは、当たり外れのある作業でした。うまくいくこともあれば、いかないこともありました。このバージョンより古い IM で使おうとすることはお勧めしません。
また、統合歪みマップと同じように、単一の「統合変位マップ」を使えます。変位画像が一つだけ提供される場合、X 変位は「red」チャンネルからルックアップされ、Y 変位は「green」チャンネルからルックアップされ、何らかのアルファマスクも変位マップから最終画像へ転送されます。「blue」チャンネルは無視されます。 _内部的には、"magick" も "magick composite" も、(提供されていれば)実際には2つの画像を統合して「統合変位マップ」を生成してから、それを内部 API に渡します。

これは、与えられた変位マップがグレースケール画像で「red」と「green」の両チャンネルが同一だったので、以前に見て扱った「線形変位」には影響しません。_
---|---

円筒変位

IM のフォーラムで何度か出てきたのは、コーヒーマグやソフトドリンクの缶に重ねるなど、画像を円筒上にマッピングする方法です。これがその解決策です…… |

  magick rose: -background black -gravity south -splice 0x8 \
          \( +clone -sparse-color barycentric '0,0 black 69,0 white' \) \
          \( -clone 1 -function arcsin 0.5 \) \
          \( -clone 1 -level 25%,75% \
                 -function polynomial -4,4,0 -gamma 2 \
                 +level 50%,0 \) \
          -delete 1 \
          -virtual-pixel black  -define compose:args=17x7 \
          -compose Displace  -composite   rose_cylinder.png

[IM Output]
上記は非常に複雑ですが、本質的には2つの別々の変位を同時に使います。X 方向の arcsin() 圧縮と、Y 方向の円弧変位です。コマンドが行っていることは次の通りです……

  • 「rose」画像を読み込み、垂直変位用のスペースを追加する
  • 後の数学的関数のために水平方向の数学的グラデーションを作成する
  • グラデーションのコピーを magick して圧縮変位マップを生成する
  • 別のコピーを magick して垂直方向の楕円弧変位にする
  • 線形グラデーションを削除する
  • 変位を準備して実行する

結果……円筒の 30 度等角投影ビューに正しく巻きつけられたバラ。上記のコマンドを分解して、個々の変位マップを保存して見てみてください。覚えておくべき鍵は、2マップ変位が X と Y 両方の値のルックアップを行い、ルックアップの位置にどのピクセルが来るべきかを割り出すということです。変位は実際にはソース画像の変位ではなく、ソース画像へのルックアップの変位であることを覚えておいてください。この変位歪みメソッドは、Fred Wienhaus による "[cylinderize](http://www.fmwconcepts.com/imagemagick/cylinderize/)" スクリプトに組み込まれています。

割れた鏡

X と Y の変位のランダムな領域を生成することで、画像に「割れた鏡」の見た目を作成できます。

  magick dragon_sm.gif -sparse-color voronoi '  \
                  %[fx:rand()*w],%[fx:rand()*h]  red
                  %[fx:rand()*w],%[fx:rand()*h]  lime
                  %[fx:rand()*w],%[fx:rand()*h]  black
                  %[fx:rand()*w],%[fx:rand()*h]  yellow
               ' -interpolate integer -implode 1     mirror_areas.gif
  magick  mirror_areas.gif -channel R  -separate   mirror_dismap_x.gif
  magick  mirror_areas.gif -channel G  -separate   mirror_dismap_y.gif

  magick composite mirror_dismap_x.gif  dragon_sm.gif  mirror_dismap_y.gif -alpha off \
            -background white -virtual-pixel background -displace 7 \
                                                        mirror_displaced.gif

  magick  mirror_areas.gif -edge 1 -threshold 20% \
            -evaluate multiply .7 -negate               mirror_cracks.gif
  magick composite mirror_displaced.gif  mirror_cracks.gif -compose multiply \
                                                        mirror_cracked.gif

[IM Output] | [IM Output] [IM Output] [IM Output] |
---|---|---
| [IM Output] [IM Output] | [IM Output]

ランダム化された Voronoi スパースカラー画像を使って、4つのランダムに変位した領域が生成されます。これに次いで爆縮歪みを与えて、それらの領域を画像の中央へとワーピングします。4つの色付き領域はそれぞれ単色のままなので、各領域には元の画像の歪んでいないが変位したコピーが含まれます。しかし、各領域は、割れた鏡の各破片がそうするのとちょうど同じように、画像を異なる方法で変位させます。鏡を仕上げるために、エッジ検出を使って領域の端、したがって結果の画像の割れた性質を輪郭づけます。つまり、ひびも見えるようにされます。 技術的には、生成された色付きのランダム変位マップで「red」と「green」チャンネルを分離する必要はありませんでした。X 変位は「red」チャンネルからルックアップされ、Y 変位は「green」チャンネルからルックアップされるので、それらを直接使えました。つまり、"mirror_areas.gif" 画像を「統合変位マップ」として直接使えたのです。

工事中

Shepards 変位

ランダム変位

レンズ効果

すりガラス効果

分散効果(回転変位)

ランダム化変位による分散効果

将来: その他の可能な歪み/変位マッピングの例

  • 後で任意の画像をそれらのオブジェクト上にマッピングできるよう、3D オブジェクト上にグラデーションをレイトレースする。
    • X と Y のグラデーションがマッピングされた画像
    • 色、ハイライト、陰影のための純粋なグレー画像

可変ぼかしマッピング

ImageMagick バージョン 6.5.4-0 で追加された "[-compose](https://imagemagick.org/command-line-options/#compose)" メソッド 'Blur' は、マッピング画像に応じて、各個別のピクセルを近傍ピクセルの楕円ガウシアン平均(ぼかし)で置き換える方法を提供します。

    magick composite -blur {_Xscale_}[x{_Yscale_}[+{_angle_}]]          blur_map  image   result

    magick image  blur_map \
        -define compose:args='{_Xscale_}[x{_Yscale_}[+{_angle_}]]' \
        -compose blur -composite   result

    magick image  blur_map \
        -set option:compose:args '{_Xscale_}[x{_Yscale_}[+{_angle_}]]' \
        -compose blur  -composite   result

この画像合成は操作引数の使用を要求することに注意してください。これはいくつかの方法で設定できます。詳細についてはグローバルに定義されたアーティファクトを参照してください。可変マップを使ってぼかしを制御することで、画像の一部をぼかしつつ別の部分をまったく手をつけずに残したり、現実世界の画像を小さな人工的な模型のように見せるティルトシフト効果のような効果を生み出したりできます。

たとえば、ここではコアラの画像の半分をぼかしつつ、もう半分をまったくぼかさずに残します……

  magick -size 37x75 xc:black -size 38x75 xc:white +append  blur_map_bool.gif
  magick koala.gif blur_map_bool.gif \
          -compose blur -define compose:args=3 -composite \
          blur_koala_bool.gif

[IM Output] [IM Output] [IM Output]

ご覧のように、「blur_map」画像で「白」だったピクセルはすべて、与えられた 'sigma ' の最大値を使ってぼかされ、「黒」だったものはまったくぼかされませんでした。言い換えれば、非常に単純なマスクされたぼかしを持っています。もちろん、これは他の多くの方法でも達成できましたが、それでぼかしマッピングの力がどこにあるかは説明できません。ぼかしマッピングを多用途にするのは、それが画像全体で可変であることです。つまり、ぼかしマッピングの色がグレーの色であれば、そのピクセルについて、より小さな「近傍」を使った、対応してより小さなぼかし結果が得られます。しかし黒はぼかされず、白は与えられた値によって最大限にぼかされます。注目すべきことの一つは、ぼかされる領域だけが必要な余分な時間を要することです。ぼかされないピクセルは、この余分な処理を必要としません。これにより、上記はマスク合成を使うより(これは画像全体をぼかして結果を統合するのと同じです)はるかに高速になります。この時間の節約は、画像の非常に小さな領域の大きなぼかしを扱う場合にさらに重要になりえます。たとえば、コアラを足に向かって徐々によりぼやけさせてみましょう……

  magick -size 75x75 gradient:black-white blur_map_gradient.gif
  magick koala.gif blur_map_gradient.gif \
          -compose blur -define compose:args=3 -composite \
          blur_koala_gradient.gif

[IM Output] [IM Output] [IM Output]

そしてここに同じぼかしが再びありますが、ぼかしが高さに応じてどう変化するかを示しています。

  magick blur_map_bool.gif blur_map_gradient.gif \
          -compose blur -define compose:args=15 -composite \
         blur_edge_gradient.gif

[IM Output] [IM Output] [IM Output]

可変マッピングぼかしの実用的な例については、写真ティルトシフト効果距離ぼかしシャドウフォントを見てください。各個別のピクセルの周りの近傍が、そのピクセルの「ぼかし色」を生成するために使われることに注意してください。つまり、画像のある部分をぼかさないよう指定しても、その領域の色が周囲のピクセルのぼかしの一部として使われる可能性があります。つまり、ある領域がぼかされないからといって、その領域の色が他のぼかされたピクセルの結果の一部として使われないわけではないのです。つまり、ぼかされない領域の色は、周囲のぼかされた領域に「漏れ出す」ことがあります。前景のピクセルを含めずに背景をぼかすには、それらがぼかし操作の一部として読み込まれるのを防ぐために、読み込みマスク技法を使う必要があります。

楕円ぼかし

'Blur' 合成設定は、通常のBlur または Gaussian Blur 演算子とは異なる技法を使います。これは、一般化歪み演算子の一部としてスケーリングされた画像リサンプリングのために開発されたガウシアン楕円領域リサンプリングアルゴリズムを使って実装されているからです。近傍リサンプリングに使われる楕円領域は、このぼかしメソッドを、演算子 "[-blur](https://imagemagick.org/command-line-options/#blur)" と "[-gaussian-blur](https://imagemagick.org/command-line-options/#gaussian-blur)" が提供する通常の一様な「円形」ぼかしよりも多用途にもします。楕円自体は、ぼかし領域のシグマの 'width '、'height ' によって定義されます。楕円は与えられた 'angle '(時計回り)によって直交配置から回転させることもできます。たとえば、次の図では、与えられたシグマ値に基づいて、単一ピクセルのぼかし色が回転した楕円領域からどのように色を得るかを示します。この領域内のピクセルは次に、(楕円距離公式を使った)ガウシアンフィルタに従って重み付け平均され、ぼかし色を生成します。

  magick koala.gif -compose blur -define compose:args=5x1-30 -composite \) \
             elliptical_blur.gif
  # ... 他のコマンドでぼかし効果の図を作成 ...

[IM Output]

述べたように、これは一般化歪み演算子が歪んだ画像の色を生成するために使うのとまったく同じ色のルックアップメソッドです。これは、特に遠い地平線を見るで例示されたような極端な歪みにおいて、ソース画像のある領域を一つのピクセルへスケーリング(およびフィルタリング)して統合することを可能にします。この処理の詳細については、領域リサンプリングリサンプリングフィルタを参照してください。

可変ぼかしマッピングに使える楕円制御の例として、以前使ったのと同じグラデーションぼかしマップを使って黒い点を使ってみましょう。ただし今回は、円ではなく、長く細い水平の楕円 '30x0' をスケーリングします。「x0」は奇妙に見えるかもしれませんが、基本的に垂直方向のぼかしは見られず、良い結果を生成するのに必要な最小の高さの楕円だけを意味します。

  magick -size 75x75 xc: -draw 'circle 36,36 36,8'  black_circle.gif
  magick black_circle.gif blur_map_gradient.gif \
          -compose blur -define compose:args=15x0 -composite \
          blur_horizontal.gif

[IM Output] [IM Output] [IM Output]

ご覧のように、ぼかしの量は提供されたマップ画像に応じてまだ変化しており、画像の上部ではほとんどぼかしを生み出さず、下部では多くのぼかしを生み出します。しかし、下端は両方向に水平に等しくぼかされていますが、垂直方向にはぼかされておらず、垂直方向に鋭い切れ目を生み出していることにも注目してください。3番目の angle 引数を与えて長く細い楕円を回転させるか、垂直の楕円を直接定義することで、画像を垂直方向のみにぼかせます…… |

  magick black_circle.gif blur_map_gradient.gif \
          -compose blur -define compose:args=0x15 -composite \
          blur_vertical.gif

[IM Output]
ただし、ぼかしが等しく適用されなかったことに注意してください! 上半分は下半分より少なくぼかされて見えます。それが「マッピング画像」がそうするよう指示したことだからです。これは次に画像を歪め、ぼかし効果によって少し切り詰められたように見せます。最後に、もう一度これを行いますが、水平の楕円を固定 45 度の角度で回転させます。 |

  magick black_circle.gif blur_map_gradient.gif \
          -compose blur -define compose:args=15x0+45 -composite \
          blur_angle.gif

[IM Output]
画像は非常に奇妙に見えるかもしれませんが、それは可変ぼかしマップが垂直であるのにぼかし自体が角度をつけられているからで、楕円の角度とぼかしマップの角度が揃わない仕方によって、奇妙に見える効果を生み出しています。 | このような長く細い楕円を使うのは、実は単一の大きな円を使うよりずっと高速であることに注意してください。実際、"[-blur](https://imagemagick.org/command-line-options/#blur)" 演算子は2つの別々の水平と垂直のぼかしを使うことでその速度を得ていますが、"[-gaussian](https://imagemagick.org/command-line-options/#gaussian)" ぼかし演算子は、いま説明した 'Blur' 合成メソッドより単純な方法で完全な2次元畳み込みを行います。
---|---

可変アスペクト比のぼかし

ここまで、「ぼかしマップ」を使ってぼかしに使われる楕円領域のサイズを変化させてきました。しかし、楕円のサイズや角度さえも回転できますが、その形と角度は固定のままでした。さて、「ぼかしマップ」は3つのカラーチャンネル、赤、緑、青で構成された画像です。グレースケール画像を使ったので、3つのカラーチャンネルすべてが同じ値を持っていました。しかし内部的には、楕円の幅は赤チャンネル値だけによってスケーリングされ、高さは緑チャンネル値によってスケーリングされます。青チャンネル値の効果は、後で見る特別な場合を除いて、通常無視されます。これは、楕円の形すなわちその「アスペクト比」を、個々の赤と緑のチャンネルに異なるマップを使うことで変化させられることを意味します。通常のぼかしマップと同様に、ゼロ(またはそのチャンネルだけで「黒」)の値は最小の幅または高さをもたらし、最大値(または「白」)は与えられたぼかし量をもたらします。たとえば、ここでは画像を分割して、画像の4分の2を水平にぼかし(赤チャンネルが最大)、他の領域を垂直にぼかす(緑チャンネルが最大)ようにできます。この例では、幅と高さのマップを別々に生成してから、それらを統合して単一のカラフルな「ぼかしマップ」にしました。通常の実践では、好きな方法でマップを作成したり、特定のぼかし効果のためにあらかじめ用意したマップを使ったりすることさえできます。

  magick -size 2x2 pattern:gray50 -sample 75x75! blur_map_r.gif
  magick blur_map_r.gif -negate blur_map_g.gif
  magick blur_map_r.gif blur_map_g.gif -background black \
          -channel RG -combine blur_map_aspect.gif
  magick black_circle.gif blur_map_aspect.gif \
          -compose blur -define compose:args=10x10 -composite \
          blur_aspect.gif

[IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]

もちろん、楕円に固定の角度を設定することもまだできます。 |

  magick black_circle.gif blur_map_aspect.gif \
          -compose blur -define compose:args=15x15+45 -composite \
          blur_aspect_angle.gif

[IM Output]
| IM バージョン 6.5.8-8 より前では、角度のついた垂直楕円ぼかしの扱いにバグが見つかっていました。
---|---

可変角度のぼかし

ここまで、画像をぼかすために使われる楕円の角度は、画像全体で一定の角度でした。つまり、ぼかしマップの赤と緑のチャンネルを変更することで楕円のアスペクト比は変化させられても、ぼかしに使われる楕円は常に同じ角度でした。IM v6.5.8-8 以降、ぼかしマッピング画像の青チャンネルを使って、ぼかしに可変の角度を与えられます。これはぼかし引数に2つの角度を与えることで行われます。最初の角度引数は青チャンネルのゼロ('0' または「黒」)の値の角度を定義するために使われ、2番目に与えられた角度は青チャンネルの最大(「QuantumRange」または「白」)の値を定義するために使われます。角度値が一つだけ与えられた場合、その角度がゼロと最大の「青」チャンネル値の両方の角度を設定するために使われ、これは基本的に、「ぼかしマップ」画像の青チャンネルにどんな値があるかに関わらず角度が固定になることを意味します。これが、以前の例で角度が一定だった理由です。たとえば、ここでは水平にぼかす楕円を使いますが、それから青チャンネルを使って、画像の中心の周りで '+0' から '+360' までの角度範囲にわたって楕円の角度を変化させます。マップの生成は極座標グラデーションを使います。その詳細は歪んだグラデーションで見つかります。そのグラデーションを青チャンネルに置く際、Combine 演算子とともに "[-background](https://imagemagick.org/command-line-options/#background)" 色設定を使って、赤と緑の両チャンネルが最大(「白」)の値に設定されるようにし、角度のついた楕円をスケーリングしないようにしている点に注目してください。もちろんそれは、最終マッピング画像で、白は最大角度を使うことを意味し、黄色(またはゼロの青チャンネル値)は最小角度を意味します。

  magick -size 100x300 gradient: -rotate 90 \
          +distort Polar '36.5,0,.5,.5' +repage -flop gradient_polar.jpg
  magick gradient_polar.jpg -background white \
          -channel B -combine blur_map_angle.jpg
  magick koala.gif blur_map_angle.jpg \
          -compose blur -define compose:args=5x0+0+360 -composite \
          blur_rotated.jpg

[IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]

結果はご覧のように回転方向にぼかされた画像です。結果を、使われたぼかしマッピングと比較してみてください。画像の上部では、グラデーションは白か黒のどちらかで、使われた引数ではこれは楕円が 0 または 360 のいずれかに角度づけられたことを意味するので、楕円は水平のままでした。下部ではグラデーションは純粋なグレーだったので、与えられた範囲の中間の角度、すなわち 180 度が使われました。これは楕円が再び水平であることを意味します。しかし画像の側面では、グラデーションは 25% または 75% グレーでした。したがって角度は 90 または 270 度のいずれかで、楕円を垂直に回転させました。他のすべての角度も従い、楕円を画像の周りで滑らかに回転させます。しかし、結果の画像の中心は本当に奇妙にぼかされました! それは楕円のサイズが一定のままで、画像の中央に向かって適切に小さくならないからです。解決策は、赤と緑のチャンネルを使って楕円のサイズも設定することです。たとえば。

  magick -size 106x106 radial-gradient: -negate \
          -gravity center -crop 75x75+0+0 +repage gradient_radial.jpg
  magick gradient_radial.jpg gradient_radial.jpg gradient_polar.jpg \
          -channel RGB -combine blur_map_polar.jpg
  magick koala.gif blur_map_polar.jpg \
          -compose blur -define compose:args=10x0+0+360 -composite \
          blur_polar.jpg

[IM Output] [IM Output] [IM Output] [IM Output]
[IM Output] [IM Output] [IM Output]

はるかに良い結果です。ただし、結果は良く見えますが、ぼかしの楕円は、真の回転方向ぼかし画像でそうあるべきように円弧に適切に湾曲していないことに注意してください。そのため、上記は真の回転方向ぼかしの近似にすぎません。しかし、小さなぼかし距離(ぼかし角度に相当)にはかなり良いです。回転方向ぼかしを行うより良い方法は、特別な極座標-逆極座標歪み技法、あるいは現在誤った名前のついたRadial Blur 演算子を使うことです。楕円の角度(青チャンネル)に使われる角度範囲を変えることで、上記を中心からの距離とともによりぼやけるラジアルブラーへ簡単に magick できます。 |

  magick koala.gif blur_map_polar.jpg \
          -compose blur -define compose:args=5x0+90+450 -composite \
          blur_radial.jpg

[IM Output]
しかし、これらのラジアル/回転ぼかし以上のこともできます。画像全体にわたって、どこででも任意の量だけぼかしを回転させスケーリングできるからです。完全な制御ができます。たとえば、異なる角度範囲を使ってぼかし楕円の角度を画像の中心の周りの角度に一致させないことで、両者の非常に奇妙な混合を作れます。 |

  magick koala.gif blur_map_polar.jpg \
          -compose blur -define compose:args=10x0+0+180 -composite \
          blur_weird.jpg

[IM Output]
基本的に、画像のどの部分がどのようにぼかされるかを完全に制御できるようになりました。そしてテンプレートを使えば、ぼかし効果のライブラリ全体を作成できます。