Filtro de mapa de deslocamento

Flash Player 9 e posterior, Adobe AIR 1.0 e posterior

A classe DisplacementMapFilter usa valores de pixel de um objeto BitmapData (conhecido como a imagem do mapa de deslocamento) para realizar um efeito de deslocamento em um novo objeto. A imagem do mapa de deslocamento normalmente é diferente do objeto de exibição ou da ocorrência de BitmapData real no qual o filtro está sendo aplicado. Um efeito de deslocamento envolve a movimentação de pixels nas imagem filtrada - em outras palavras, deslocá-los do local original para alguma posição. Esse filtro pode ser usado para criar um efeito alterado, distorcido ou matizado.

O local e a quantidade de deslocamento aplicados em um determinado pixel são especificados pelo valor de cor da imagem do mapa de deslocamento. Ao trabalhar com o filtro, além de especificar a imagem do mapa, você especifica os seguintes valores para controlar como o deslocamento é calculado a partir da imagem do mapa:

  • Ponto do mapa: o local da imagem filtrada na qual o canto superior esquerdo do filtra de deslocamento será aplicado. Use esse ponto apenas se desejar aplicar o filtro em parte de uma imagem.

  • Componente X: canal de cor da imagem do mapa que afeta a posição x dos pixels.

  • Componente Y: canal de cor da imagem do mapa que afeta a posição y dos pixels.

  • Escala X: um valor de multiplicador que especifica a intensidade do deslocamento do eixo x.

  • Escala Y: um valor de multiplicador que especifica a intensidade do deslocamento do eixo y.

  • Modo de filtro: determina o que fazer em qualquer espaço vazio criado pelos pixels que estão sendo alterados. As opções, definidas como constantes na classe DisplacementMapFilterMode, devem exibir os pixels originais (modo de filtro IGNORE ), colocar os pixels em torno do outro lado da imagem (modo de filtro WRAP , que é o padrão), usar o pixel alterado mais próximo (modo de filtro CLAMP ) ou preencher os espaços com uma cor (modo de filtro COLOR ).

Para entender o funcionamento do filtro do mapa de deslocamento, considere um exemplo simples. No código a seguir, uma imagem é carregada e, em seguida, centralizada no palco. Um filtro de mapa de deslocamento é aplicado, fazendo com que os pixels da imagem inteira mudem horizontalmente para a esquerda.

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

As propriedades usadas para definir o deslocamento são as seguintes:

  • Bitmap de mapa: o bitmap de deslocamento é uma nova ocorrência de BitmapData criada pelo código. Suas dimensões coincidem com as dimensões da imagem carregada (de modo que o deslocamento é aplicado na imagem inteira). Ela é preenchida com pixels vermelhos sólidos.

  • Ponto do mapa: esse valor é definido como o ponto 0, 0 - mais uma vez, o deslocamento será aplicado na imagem inteira.

  • Componente X: esse valor é definido como a constante BitmapDataChannel.RED , o que significa que o valor vermelho do bitmap de mapa determinará o deslocamento dos pixels (o quanto se movimentam) ao longo do eixo x.

  • Escala X: esse valor é definido como 250. O valor total de deslocamento (a partir da imagem do mapa que está completamente vermelha) desloca a imagem apenas um pouco (aproximadamente metade de um pixel), de modo que, se esse valor fosse definido como 1, a imagem seria movida apenas 0,5 pixel na horizontal. Se esse valor for definido como 250, a imagem será deslocada aproximadamente 125 pixels.

Essas configurações fazem com que os pixels da imagem filtrada sejam deslocados 250 pixels para a esquerda. A direção (esquerda ou direita) e o valor do deslocamento baseiam-se no valor de cor dos pixels da imagem do mapa. Conceitualmente, o filtro percorre cada pixel da imagem filtrada (pelo menos os pixels da região onde o filtro é aplicado que, nesse caso, são todos os pixels) e faz o seguinte com cada pixel:

  1. Localiza o pixel correspondente na imagem do mapa. Por exemplo, quando o filtro calcula o valor de deslocamento para o pixel no canto superior esquerdo da imagem filtrada, será observado o pixel no canto superior esquerdo da imagem do mapa.

  2. Determina o valor do canal de cor especificado no pixel do mapa. Nesse caso, o canal de cor do componente x é o canal vermelho, de modo que o filtro observa qual é o valor do canal vermelho da imagem do mapa no pixel em questão. Como a imagem do mapa é vermelho sólido, o canal vermelho do pixel é 0xFF ou 255. Esse valor é usado como valor de deslocamento.

  3. Compara o valor de deslocamento com o valor "central" (127, que é o valor médio entre 0 e 255). Se o valor de deslocamento for inferior ao valor médio, o pixel será deslocado em uma direção positiva (para a direita no deslocamento x; para baixo no deslocamento y). Por outro lado, se o valor de deslocamento for maior do que o valor médio (como neste exemplo), o pixel será deslocado em uma direção negativa (para a esquerda no deslocamento x; para cima no deslocamento y). Para ser mais preciso, o filtro subtrai o valor de deslocamento de 127 e o resultado (positivo ou negativo) é o valor relativo do deslocamento que é aplicado.

  4. Finalmente, ele determina o valor real de deslocamento definindo qual porcentagem de deslocamento completo é representado pelo valor de deslocamento relativo. Nesse caso, vermelho total indica 100% de deslocamento. Essa porcentagem é multiplicada pelo valor da escala x ou y para determinar o número de pixels do deslocamento que será aplicado. Neste exemplo, 100% vezes um multiplicador igual a 250 determina o valor de deslocamento - aproximadamente 125 pixels para a esquerda.

Como nenhum valor foi especificado para o componente e a escala y, os padrões (que não provocam nenhum deslocamento) foram usados; é por esse motivo que a imagem não é alterada na vertical.

A configuração padrão do modo de filtro, WRAP , é usada no exemplo, de modo que os pixels se movem para a esquerda e o espaço vazio à direita é preenchido pelos pixels que se deslocaram da margem esquerda da imagem. Você pode experimentar esse valor para ver os diferentes efeitos. Por exemplo, se você adicionar a linha a seguir à parte do código onde as propriedades de deslocamento estão sendo definidas (antes da linha loader.filters = [displacementMap] ), a imagem parecerá ter sido manchada ao longo do palco:

displacementMap.mode = DisplacementMapFilterMode.CLAMP;

Em exemplos mais complexos, a listagem a seguir usa um filtro de mapa de deslocamento para criar um efeito de lupa em uma imagem:

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

Primeiro, o código gera dois círculos de gradiente, que são combinados para formar a imagem do mapa de deslocamento. O círculo vermelho cria o deslocamento do eixo x ( xyFilter.componentX = BitmapDataChannel.RED ) e o círculo azul cria o deslocamento do eixo y ( xyFilter.componentY = BitmapDataChannel.BLUE ). Para ajudar você a entender como se parece a imagem do mapa de deslocamento, o código adiciona os círculos originais, bem como o círculo combinado que serve como a imagem do mapa, à parte inferior da tela.

Imagem que exibe a foto de uma flor com um trecho ampliado sob o cursor do mouse.

Em seguida, o código carrega uma imagem e, à medida que o mouse se move, aplica o filtro de deslocamento na parte da imagem que está embaixo do mouse. Os círculos de gradiente usados como a imagem do mapa de deslocamento fazem com que a região deslocada se distancie do ponteiro. Observe que as regiões de cinza da imagem do mapa não provocam nenhum deslocamento. A cor de cinza é 0x7F7F7F . Os canais azul e vermelho dessa sombra de cinza correspondem exatamente à sombra central desses canais de cor, de modo que não há nenhum deslocamento em uma área de cinza da imagem do mapa. Do mesmo modo, não há nenhum deslocamento no centro do círculo. Embora a cor não seja cinza, os canais azul e vermelho dessa cor são idênticos aos canais azul e vermelho do cinza médio e, como azul e vermelho são as cores que provocam o deslocamento, não ocorre nenhum deslocamento aqui.