La classe DisplacementMapFilter utilizza valori di pixel di un oggetto BitmapData (detto immagine mappa di spostamento) per applicare un effetto di spostamento su un nuovo oggetto. Di solito l'immagine della mappa di spostamento è diversa dall'oggetto di visualizzazione vero e proprio o dall'istanza BitmapData a cui si applica il filtro. Un effetto di spostamento richiede lo spostamento dei pixel nell'immagine filtrata (in altre parole, il loro spostamento dalla posizione originale). Questo filtro può essere utilizzato per creare un effetto spostato, deformato o screziato.
La posizione e la quantità dello spostamento applicato a un determinato pixel vengono determinate dal valore di colore dell'immagine della mappa di spostamento. Quando utilizzate il filtro, oltre a specificare l'immagine della mappa, dovete specificare i valori seguenti per controllare il modo in cui viene calcolato lo spostamento rispetto all'immagine della mappa:
-
Punto mappa: la posizione dell'immagine filtrata in corrispondenza della quale viene applicato l'angolo superiore sinistro del filtro spostamento. Potete utilizzarla solo se desiderate applicare il filtro a una parte di un'immagine.
-
Componente X: indica il canale colore dell'immagine della mappa che influisce sulla posizione x dei pixel.
-
Componente Y: indica il canale colore dell'immagine della mappa che influisce sulla posizione y dei pixel.
-
Scala X: valore moltiplicatore che specifica l'intensità dello spostamento dell'asse x.
-
Scala Y: valore moltiplicatore che specifica l'intensità dello spostamento dell'asse y.
-
Modalità filtro: determina cosa fare negli spazi vuoti creati dai pixel spostati. Le opzioni disponibili, definite come costanti nella classe DisplacementMapFilterMode, sono le seguenti: visualizzazione dei pixel originali (modalità filtro
IGNORE
), applicazione dei pixel dell'altro lato dell'immagine (modalità filtro
WRAP
, predefinita), utilizzo del pixel spostato più vicino (modalità filtro
CLAMP
) o riempimento degli spazi con un colore (modalità filtro
COLOR
).
Per comprendere come funziona la mappa di spostamento, considerate il seguente esempio. Nel codice seguente viene caricata un'immagine che, al termine del caricamento, viene centrata sullo stage. All'immagine viene quindi applicato un filtro mappa di spostamento, in base al quale i pixel dell'intera immagine vengono spostati in senso orizzontale verso sinistra.
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);
Di seguito sono riportate le proprietà utilizzate per definire lo spostamento:
-
Bitmap mappa: la bitmap di spostamento è una nuova istanza BitmapData creata dal codice. Le sue dimensioni corrispondono a quelle dell'immagine caricata (pertanto lo spostamento viene applicato all'intera immagine) ed è riempita con pixel rossi uniformi.
-
Punto mappa: questo valore è impostato sul punto 0, 0 e anche in questo caso provoca l'applicazione dello spostamento all'intera immagine.
-
Componente X: questo valore viene impostato sulla costante
BitmapDataChannel.RED
; ciò significa che il valore rosso della bitmap della mappa determina la quantità di spostamento dei pixel lungo l'asse x.
-
Scala X: questo valore è impostato su 250. La quantità di spostamento (dipendente dal fatto che l'immagine della mappa è completamente rossa) sposta l'immagine solo di poco (circa mezzo pixel), pertanto se questo valore viene impostato su 1 l'immagine si sposta solo di 0,5 pixel in orizzontale. Se il valore impostato è 250, l'immagine si sposta di circa 125 pixel.
In base a queste impostazioni, i pixel dell'immagine filtrata vengono spostati di 250 pixel verso sinistra. La direzione (sinistra o destra) e la quantità dello spostamento si basano sul valore di colore dei pixel nell'immagine della mappa. In teoria, il filtro scorre uno a uno i pixel dell'immagine filtrata (perlomeno, i pixel nell'area in cui è applicato il filtro, che in questo caso significa tutti i pixel) e per ogni pixel effettua le operazioni seguenti:
-
Trova il pixel corrispondente nella mappa dell'immagine. Quando, ad esempio, il filtro calcola la quantità di spostamento per il pixel nell'angolo superiore sinistro dell'immagine filtrata, cerca il pixel nell'angolo superiore sinistro dell'immagine della mappa.
-
Determina il valore del canale di colore specificato nel pixel della mappa. In questo caso, il canale di colore del componente x è il canale rosso, pertanto il filtro verifica se il canale rosso dell'immagine della mappa si trova in corrispondenza del pixel in questione. Dal momento che la mappa dell'immagine è rosso uniforme, il canale rosso del pixel è 0xFF, o 255. Questo valore viene utilizzato come valore di spostamento.
-
Confronta il valore di spostamento con il valore “medio” (ovvero 127, che si trova a metà tra 0 e 255). Se il valore di spostamento è inferiore al valore medio, il pixel si sposta in una direzione positiva (a destra per lo spostamento x, verso il basso per lo spostamento y). Se, invece, il valore di spostamento è superiore al valore medio (come accade in questo esempio), il pixel si sposta in una direzione negativa (a sinistra per lo spostamento x, verso l'alto per lo spostamento y). Per maggiore precisione, il filtro sottrae il valore di spostamento da 127 e il risultato (positivo o negativo) rappresenta la quantità relativa di spostamento che viene applicata.
-
Infine, determina la quantità effettiva di spostamento determinando la percentuale di spostamento completo rappresentata dal valore di spostamento relativo. In questo caso, il rosso pieno significa uno spostamento del 100%. Tale percentuale viene quindi moltiplicata per il valore della scala x o della scala y per determinare il numero di pixel di spostamento da applicare. In questo esempio, 100% moltiplicato per un moltiplicatore di 250 determina la quantità di spostamento: circa 125 pixel verso sinistra.
Dal momento che non sono stati specificati valori per il componente y e la scala y, sono stati utilizzati i valori predefiniti (che non provocano alcuno spostamento); pertanto l'immagine non viene spostata in direzione verticale.
Nell'esempio viene utilizzata l'impostazione predefinita della modalità filtro,
WRAP
; pertanto mentre i pixel vengono spostati verso sinistra, lo spazio vuoto a destra viene riempito con i pixel che sono stati esclusi dallo spostamento del bordo sinistro dell'immagine. Potete fare delle prove con questo valore per osservare il comportamento dei diversi effetti. Se, ad esempio, aggiungete la riga seguente alla porzione di codice in cui sono impostate le proprietà dello spostamento (prima della riga
loader.filters = [displacementMap]
), l'effetto che ottenete è quello di un'immagine sfumata su tutto lo stage:
displacementMap.mode = DisplacementMapFilterMode.CLAMP;
Per un esempio più complesso, il codice seguente utilizza un filtro mappa di spostamento per creare un effetto lente di ingrandimento su un'immagine:
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);
Il codice genera innanzi tutto due cerchi con gradiente, che vengono combinati per formare l'immagine della mappa di spostamento. Il cerchio rosso crea lo spostamento dell'asse x (
xyFilter.componentX = BitmapDataChannel.RED
), mentre quello blu crea lo spostamento dell'asse y (
xyFilter.componentY = BitmapDataChannel.BLUE
). Per semplificare l'aspetto dell'immagine della mappa di spostamento, il codice aggiunge sia i cerchi originali che i cerchi combinati che fungono da immagine della mappa nella parte inferiore dello schermo.
Quindi, il codice carica un'immagine e, quando il mouse si sposta, applica il filtro spostamento alla porzione dell'immagine che si trova sotto il mouse. I cerchi con gradiente utilizzati come immagine della mappa di spostamento provocano la diffusione dell'area spostata rispetto al puntatore del Notate che le aree grigie dell'immagine della mappa di spostamento non provocano alcuno spostamento. Il colore grigio è
0x7F7F7F
. I canali blu e rosso di tale tonalità di grigio corrispondono esattamente alla tonalità media di tali canali di colore, pertanto non viene effettuato alcuno spostamento in un'area grigia dell'immagine della mappa. In modo analogo, al centro del cerchio non avviene alcuno spostamento. Benché in tale area il colore non sia grigio, i canali blu e rosso del colore sono identici ai canali blu e rosso del grigio medio, e poiché il blu e il rosso sono i colori che provocano lo spostamento, in tale area non si verifica alcuno spostamento.