Filtre Mappage de déplacement

Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures

La classe DisplacementMapFilter utilise des valeurs de pixel extraites d’un objet BitmapData (appelé image de mappage du déplacement) pour appliquer un effet de déplacement à un nouvel objet. L’image de mappage du déplacement est en général différente de l’occurrence d’objet d’affichage ou BitmapData à laquelle le filtre est appliqué. L’effet de déplacement nécessite de déplacer les pixels de l’image filtrée, autrement dit de les décaler d’un certain niveau. Ce filtre permet de créer un effet de décalage, de gondole ou de marbrure.

La direction et la valeur du déplacement appliqué à un pixel donné sont déterminées par la valeur colorimétrique de l’image de mappage du déplacement. Pour utiliser ce filtre, il est nécessaire de spécifier l’image de mappage, ainsi que les valeurs suivantes, qui permettent de contrôler le calcul du déplacement :

  • Point de mappage : emplacement, dans l’image filtrée, auquel le coin supérieur gauche du filtre de déplacement sera appliqué. Ce paramètre n’est nécessaire que pour appliquer le filtre à une partie de l’image seulement.

  • Composant X : canal couleur de l’image de mappage qui affecte la position x des pixels.

  • Composant Y : canal couleur de l’image de mappage qui affecte la position y des pixels.

  • Echelle X : valeur multiplicatrice qui indique le niveau de déplacement sur l’axe x.

  • Echelle Y : valeur multiplicatrice qui indique le niveau de déplacement sur l’axe y.

  • Mode de filtrage : détermine la marche à suivre dans le cas d’espaces vides créés par le décalage des pixels. Les options, définies par des constantes dans la classe DisplacementMapFilterMode, sont d’afficher les pixels originaux (mode IGNORE ), de décaler et transférer les pixels de l’autre côté de l’image (mode WRAP , qui est le mode par défaut), d’utiliser le pixel déplacé le plus proche (mode CLAMP ) ou de remplir ces espaces vides avec une couleur (mode COLOR ).

Pour comprendre le fonctionnement d’un filtre de mappage de déplacement, prenons un exemple simple. Dans le code ci-dessous, une image est chargée, puis elle est centrée sur la scène et un filtre Mappage de déplacement lui est appliqué, ce qui déplace horizontalement (vers la gauche) les pixels de toute l’image.

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);

Les propriétés utilisées pour définir le déplacement sont les suivantes :

  • Bitmap de mappage : le bitmap de déplacement est une nouvelle occurrence de BitmapData, créée par code. Ses dimensions sont identiques à celles de l’image chargée (le déplacement est donc appliqué à toute l’image). Elle est remplie de pixels rouges opaques.

  • Point de mappage : cette valeur est définie pour le point 0, 0 (ici encore, le déplacement sera appliqué à toute l’image).

  • Composant X : cette valeur reçoit la constante BitmapDataChannel.RED , ce qui signifie que c’est la valeur de rouge de l’image bitmap de mappage qui déterminera le niveau de déplacement des pixels sur l’axe x.

  • Echelle X : cette valeur est réglée sur 250. L’image de mappage étant entièrement rouge, la valeur totale de déplacement ne décale l’image que faiblement (environ un demi-pixel). Si cette valeur était de 1, l’image ne serait donc décalée que de 0,5 pixel horizontalement. En choisissant une valeur de 250, nous déplaçons l’image d’environ 125 pixels.

Ces valeurs provoquent un déplacement des pixels de l’image filtrée de 250 pixels à gauche. La direction (gauche ou droite) et l’importance du déplacement dépendent de la valeur colorimétrique des pixels de l’image de mappage. Le principe de fonctionnement de ce filtre est le suivant : il analyse un par un les pixels de l’image filtrée (ou tout au moins ceux de la zone à laquelle le filtre est appliqué, ce qui ici signifie toute l’image), et procède comme suit pour chaque pixel :

  1. Il détermine le pixel correspondant dans l’image de mappage. Par exemple, pour calculer la valeur de déplacement du pixel du coin supérieur gauche de l’image filtrée, le filtre analyse le pixel correspondant dans le coin supérieur gauche de l’image de mappage.

  2. Il détermine la valeur du canal de couleur spécifié dans le pixel de mappage. Dans cet exemple, le canal de couleur du composant x est le rouge. Le filtre recherche donc la valeur du canal rouge au point en question dans l’image de mappage. L’image de mappage étant un rouge opaque, le canal rouge du pixel a la valeur 0xFF, soit 255. Cette valeur est la valeur de déplacement.

  3. Ils comparent ensuite la valeur de déplacement à la valeur médiane (127, à mi-chemin entre 0 et 255). Si la valeur de déplacement est inférieure à la valeur médiane, le pixel est déplacé dans une direction positive (vers la droite pour l’axe x, vers le bas pour l’axe y). Par contre, si la valeur de déplacement est supérieure à la valeur médiane (comme dans cet exemple), le pixel est déplacé dans une direction négative (vers la gauche pour l’axe x, vers le haut pour l’axe y). Plus précisément, le filtre soustrait la valeur de déplacement de 127, et le résultat (positif ou négatif) est la valeur relative de déplacement qui est appliquée.

  4. Enfin, ils déterminent la valeur réelle de déplacement en calculant le pourcentage de déplacement complet représenté par la valeur de déplacement relatif. Dans cet exemple, un rouge à 100 % provoque un déplacement de 100 %. Ce pourcentage est ensuite multiplié par la valeur de l’échelle x ou de l’échelle y pour déterminer le nombre de pixels de déplacement à appliquer. Dans cet exemple, la valeur de déplacement est 100 % multiplié par un multiple de 250, soit environ 125 pixels à gauche.

Comme nous ne spécifions aucune valeur pour les composants x et y, les valeurs par défaut (qui ne provoquent pas de déplacement) sont utilisées. C’est pourquoi l’image n’est pas déplacée dans le sens vertical.

Dans cet exemple, le paramètre par défaut de mode de filtrage, WRAP , est utilisé, si bien que lorsque les pixels sont déplacés vers la gauche, l’espace laissé vide à droite est rempli par les pixels qui ont été décalés le long du côté gauche de l’image. Vous pouvez modifier cette valeur pour voir les différents effets ainsi obtenus. Par exemple, si vous ajoutez la ligne suivante dans la partie du code qui définit les propriétés de déplacement (avant la ligne loader.filters = [displacementMap] ), l’image semble avoir subi un balayage :

displacementMap.mode = DisplacementMapFilterMode.CLAMP;

Le code ci-dessous propose un exemple plus complexe, en utilisant un filtre Mappage de déplacement pour créer un effet de loupe dans l’image :

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);

Ce code génère d’abord deux cercles en dégradé, qui sont combinés pour former l’image de mappage du déplacement. Le cercle rouge est à l’origine du déplacement sur l’axe x ( xyFilter.componentX = BitmapDataChannel.RED ) et le cercle bleu est à l’origine du déplacement sur l’axe y ( xyFilter.componentY = BitmapDataChannel.BLUE ). Pour vous permettre de comprendre plus aisément l’aspect de l’image de mappage du déplacement, le code affiche les cercles originaux, ainsi que le cercle combiné qui fait office d’image de mappage, en bas de l’écran.

Image illustrant une photo de fleur associée à une section en forme de cercle agrandie sous le curseur de la souris

Le code charge ensuite une image et, en fonction des déplacements de la souris, applique le filtre de déplacement à la partie de l’image qui est sous la souris. Les cercles dégradés utilisés pour l’image de mappage de déplacement provoquent un effet centrifuge dans la zone à laquelle le filtre est appliqué. Notez que les zones en gris de l’image de mappage du déplacement ne provoquent pas de déplacement. En effet, la valeur du gris est 0x7F7F7F . Les canaux bleu et rouge de ce niveau de gris ont donc exactement une valeur médiane, si bien qu’il n’y a pas de déplacement lorsqu’une zone grise apparaît dans l’image de mappage. Il n’y a pas non plus de déplacement au centre du cercle. Bien que cette zone ne soit pas de couleur grise, ses canaux rouge et bleu ont des valeurs identiques à celles des canaux rouge et bleu du gris moyen, et puisque le déplacement est basé sur les valeurs de bleu et de rouge, aucun déplacement n’a lieu.