置き換えマップフィルター

Flash Player 9 以降、Adobe AIR 1.0 以降

DisplacementMapFilter クラスでは、BitmapData オブジェクト(置き換えマップイメージと呼ばれる)のピクセル値を使用して、新しいオブジェクトに置き換え効果を実行することができます。通常、置き換えマップイメージは、フィルターの適用先となる実際の表示オブジェクトや BitmapData インスタンスとは異なります。 置き換え効果では、フィルターを適用したイメージのピクセルが置き換えられます。つまり、ピクセルが元の位置から若干シフトします。このフィルターを使用して、シフト効果、ワープ効果、または斑点効果を生成することができます。

個々のピクセルに適用される置き換えの位置と量は、置き換えマップイメージのカラー値に基づいて決定されます。 このフィルターを操作するときには、マップイメージの指定に加えて、マップイメージに基づいて置き換えをどのように計算するかを制御する次の値を指定する必要があります。

  • マップポイント:フィルターの適用対象となるイメージ上の位置であり、この位置に置き換えフィルターの左上隅が適用されます。イメージの一部にのみフィルターを適用する場合に使用できます。

  • X コンポーネント : マップイメージのカラーチャンネルのうち、ピクセルの x 方向位置に影響するものを示します。

  • Y コンポーネント : マップイメージのカラーチャンネルのうち、ピクセルの y 方向位置に影響するものを示します。

  • X スケール : x 軸方向の置き換えの拡大の程度を指定する乗数値です。

  • X スケール : y 軸方向の置き換えの拡大の程度を指定する乗数値です。

  • フィルターモード:ピクセルのシフトによって生じた空白の領域に対する処理を決定します。オプションは DisplacementMapFilterMode クラスの定数として定義されており、元のピクセルを表示する(フィルターモード IGNORE )か、イメージの反対側でピクセルを折り返す(フィルターモード WRAP 、デフォルト)か、最も近くにあるシフトしたピクセルを使用する(フィルターモード CLAMP )か、またはその領域をカラーで塗りつぶす(フィルターモード COLOR )ことができます。

配置マップフィルターの仕組みを理解するために、基本的な例について検討してみましょう。次のコードでは、イメージをロードし、ロードが完了したらイメージをステージの中央に移動して、置き換えマップフィルターをそのイメージに適用します。その結果、イメージ全体のピクセルが左方向に水平にシフトします。

import flash.display.BitmapData; 
import flash.display.Loader; 
import flash.events.MouseEvent; 
import flash.filters.DisplacementMapFilter; 
import flash.geom.Point; 
import flash.net.URLRequest; 
 
// Load an image onto the Stage. 
var loader:Loader = new Loader(); 
var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image3.jpg"); 
loader.load(url); 
this.addChild(loader); 
 
var mapImage:BitmapData; 
var displacementMap:DisplacementMapFilter; 
 
// This function is called when the image finishes loading. 
function setupStage(event:Event):void  
{ 
    // Center the loaded image on the Stage. 
    loader.x = (stage.stageWidth - loader.width) / 2;  
    loader.y = (stage.stageHeight - loader.height) / 2; 
     
    // Create the displacement map image. 
    mapImage = new BitmapData(loader.width, loader.height, false, 0xFF0000); 
     
    // Create the displacement filter. 
    displacementMap = new DisplacementMapFilter(); 
    displacementMap.mapBitmap = mapImage; 
    displacementMap.mapPoint = new Point(0, 0); 
    displacementMap.componentX = BitmapDataChannel.RED; 
    displacementMap.scaleX = 250; 
    loader.filters = [displacementMap]; 
} 
 
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, setupStage);

置き換えの定義に使用されているプロパティは次のとおりです。

  • マップビットマップ : 置き換えビットマップは、このコードで作成する新しい BitmapData インスタンスです。 サイズは、ロードされるイメージのサイズと一致しています。したがって、置き換えはイメージ全体に適用されます。 赤一色のピクセルで塗りつぶされています。

  • マップポイント:この値はポイント (0, 0) に設定されています。これも、置き換えがイメージ全体に適用されるようにするためです。

  • X コンポーネント:この値は定数 BitmapDataChannel.RED に設定されています。つまり、ピクセルがどの程度 x 軸方向に置き換えられる(移動する)かについては、マップビットマップの赤の値に基づいて決定されます。

  • X スケール:この値は 250 に設定されています。マップイメージの色が完全な赤で、置き換え量が最大(フル)になる場合でも、それに対応する実際のイメージの置き換えはごくわずかな量(1/2 ピクセル程度)です。そのため、この値が 1 に設定されていると、イメージは 0.5 ピクセルしか水平方向にシフトしません。 250 に設定すると、イメージは約 125 ピクセル分シフトします。

これらの設定の結果、フィルターが適用されたイメージは 250 ピクセル左方向にシフトするようになります。シフトの方向(左または右)と量は、マップイメージ内のピクセルのカラー値に基づいて決まります。 概念的には、フィルターが適用されたイメージのピクセルが 1 つずつ処理されます。少なくとも、フィルターが適用された領域のピクセル(ここで示した例ではすべてのピクセル)が処理されます。ピクセルごとに次の処理が行われます。

  1. マップイメージ内の対応するピクセルが特定されます。 例えば、フィルターが適用されたイメージの左上隅のピクセルの置き換え量が計算されるときには、マップイメージの左上隅のピクセルが参照されます。

  2. マップ上のピクセルで、指定されたカラーチャンネルの値が判定されます。 ここで示した例では、x コンポーネントに指定されたカラーチャンネルは赤チャンネルです。そのため、対象のピクセルの位置でマップイメージの赤チャンネルの値が調べられます。マップイメージが単色の赤なので、ピクセルの赤チャンネルは 0xFF または 255 です。この値は置き換え値として使用されます。

  3. 置き換え値が「中間」値と比較されます。中間値は、0 ~ 255 の中間にあたる 127 です。置き換え値が中間値よりも小さい場合、正の方向(x 置き換えでは右方向、y 置き換えでは下方向)にピクセルがシフトします。 一方、ここで示した例のように置き換え値が中間値よりも大きい場合には、負の方向(x 置き換えでは左方向、y 置き換えでは上方向)にピクセルがシフトします。 さらに正確に説明すると、127 から置き換え値が減算され、その結果(正または負)が、適用される相対的な置き換え量になります。

  4. 最後に、実際の置き換え量が決定されます。そのために、相対的な置き換え量の値が最大置き換えの何パーセントに相当するかが判定されます。 ここで示した例では、完全な赤の場合に 100% の置き換えになります。 続いて、そのパーセント値と x スケール値または y スケール値が乗算されて、適用される置き換えピクセル数が決定されます。 ここで示した例では、100% に乗数 250 を掛けて、置き換え量が決定されます。これは左方向に約 125 ピクセルになります。

y コンポーネントと y スケールについては、値が指定されていないため、デフォルト設定が使用されます。デフォルト設定では置き換えが発生しません。イメージが垂直方向にシフトしないのはこのためです。

ここで示した例では、デフォルトのフィルターモード設定である WRAP が使用されます。そのため、ピクセルが左方向にシフトしたとき、右側に生じる空白の領域は、イメージの左端から押し出されたピクセルで塗りつぶされます。この値を変更してみると、様々な効果を確認できます。 例えば、置き換えの各プロパティを設定しているコードの部分( loader.filters = [displacementMap] と記述されている行の前)に次の行を追加すると、イメージは、ステージ上でにじんだように見えるようになります。

displacementMap.mode = DisplacementMapFilterMode.CLAMP;

さらに複雑な例を示します。次のリストでは、置き換えマップフィルターを使用して、イメージに拡大鏡の効果を付加します。

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.display.BitmapDataChannel; 
import flash.display.GradientType; 
import flash.display.Loader; 
import flash.display.Shape; 
import flash.events.MouseEvent; 
import flash.filters.DisplacementMapFilter; 
import flash.filters.DisplacementMapFilterMode; 
import flash.geom.Matrix; 
import flash.geom.Point; 
import flash.net.URLRequest; 
 
// Create the gradient circles that will together form the  
// displacement map image 
var radius:uint = 50; 
 
var type:String = GradientType.LINEAR; 
var redColors:Array = [0xFF0000, 0x000000]; 
var blueColors:Array = [0x0000FF, 0x000000]; 
var alphas:Array = [1, 1]; 
var ratios:Array = [0, 255]; 
var xMatrix:Matrix = new Matrix(); 
xMatrix.createGradientBox(radius * 2, radius * 2); 
var yMatrix:Matrix = new Matrix(); 
yMatrix.createGradientBox(radius * 2, radius * 2, Math.PI / 2); 
 
var xCircle:Shape = new Shape(); 
xCircle.graphics.lineStyle(0, 0, 0); 
xCircle.graphics.beginGradientFill(type, redColors, alphas, ratios, xMatrix); 
xCircle.graphics.drawCircle(radius, radius, radius); 
 
var yCircle:Shape = new Shape(); 
yCircle.graphics.lineStyle(0, 0, 0); 
yCircle.graphics.beginGradientFill(type, blueColors, alphas, ratios, yMatrix); 
yCircle.graphics.drawCircle(radius, radius, radius); 
 
// Position the circles at the bottom of the screen, for reference. 
this.addChild(xCircle); 
xCircle.y = stage.stageHeight - xCircle.height; 
this.addChild(yCircle); 
yCircle.y = stage.stageHeight - yCircle.height; 
yCircle.x = 200; 
 
// Load an image onto the Stage. 
var loader:Loader = new Loader(); 
var url:URLRequest = new URLRequest("http://www.helpexamples.com/flash/images/image1.jpg"); 
loader.load(url); 
this.addChild(loader); 
 
// Create the map image by combining the two gradient circles. 
var map:BitmapData = new BitmapData(xCircle.width, xCircle.height, false, 0x7F7F7F); 
map.draw(xCircle); 
var yMap:BitmapData = new BitmapData(yCircle.width, yCircle.height, false, 0x7F7F7F); 
yMap.draw(yCircle); 
map.copyChannel(yMap, yMap.rect, new Point(0, 0), BitmapDataChannel.BLUE, BitmapDataChannel.BLUE); 
yMap.dispose(); 
 
// Display the map image on the Stage, for reference. 
var mapBitmap:Bitmap = new Bitmap(map); 
this.addChild(mapBitmap); 
mapBitmap.x = 400; 
mapBitmap.y = stage.stageHeight - mapBitmap.height; 
 
// This function creates the displacement map filter at the mouse location. 
function magnify():void 
{ 
    // Position the filter. 
    var filterX:Number = (loader.mouseX) - (map.width / 2); 
    var filterY:Number = (loader.mouseY) - (map.height / 2); 
    var pt:Point = new Point(filterX, filterY); 
    var xyFilter:DisplacementMapFilter = new DisplacementMapFilter(); 
    xyFilter.mapBitmap = map; 
    xyFilter.mapPoint = pt; 
    // The red in the map image will control x displacement. 
    xyFilter.componentX = BitmapDataChannel.RED; 
    // The blue in the map image will control y displacement. 
    xyFilter.componentY = BitmapDataChannel.BLUE; 
    xyFilter.scaleX = 35; 
    xyFilter.scaleY = 35; 
    xyFilter.mode = DisplacementMapFilterMode.IGNORE; 
    loader.filters = [xyFilter]; 
} 
 
// This function is called when the mouse moves. If the mouse is 
// over the loaded image, it applies the filter. 
function moveMagnifier(event:MouseEvent):void 
{ 
    if (loader.hitTestPoint(loader.mouseX, loader.mouseY)) 
    { 
        magnify(); 
    } 
} 
loader.addEventListener(MouseEvent.MOUSE_MOVE, moveMagnifier);

このコードでは、まずグラデーション塗りを適用した円が 2 つ生成されます。これらを合成することによって置き換えマップイメージが形成されます。 赤色の円は x 軸方向の置き換えを実現するためのもので( xyFilter.componentX = BitmapDataChannel.RED )、青色の円は y 軸方向の置き換えを実現するためのものです( xyFilter.componentY = BitmapDataChannel.BLUE )。また、置き換えマップイメージがどのようなものかを容易に把握できるようにするため、元の円が、マップイメージとなる合成後の円と共に画面下部に追加されます。

マウスカーソルの下で円形の部分が拡大された花の写真を示す画像。

このコードでは、さらにイメージがロードされ、マウスが移動するとマウスポインターの下にある部分のイメージに置き換えフィルターが適用されます。グラデーション塗りを適用した円が置き換えマップイメージとして使用されているため、置き換えが適用された領域は、ポインターを中心として周囲に広がります。置き換えマップイメージのグレーの領域では、置き換えは発生しません。このグレーのカラーは 0x7F7F7F です。この階調がグレーの場合、青チャンネルと赤チャンネルの値は、それぞれのカラーチャンネルの階調範囲の中央の値とちょうど一致します。そのため、マップイメージのグレーの領域では置き換えが発生しません。 同様に、円の中心でも置き換えが発生しません。 この位置のカラーはグレーではありません。しかし、このカラーの青チャンネルと赤チャンネルの値は、赤、緑、青のちょうど中間のグレーの青チャンネルおよび赤チャンネルの値と一致しています。置き換えを発生させるカラーは青と赤です。したがって、この位置では置き換えが発生しません。