Filtr Mapa przemieszczeńFlash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje Klasa DisplacementMapFilter wykorzystuje wartości pikseli z obiektu BitmapData (znanego jako obraz mapy przemieszczeń) w celu uzyskania efektu przemieszczenia na nowym obiekcie. Obraz stanowiący mapę przemieszczeń jest zazwyczaj obiektem innym niż dany obiekt wyświetlany czy instancja BitmapData, na którą nakładany jest filtr. Efekt przemieszczenia obejmuje przemieszczanie pikseli w obrazie filtrowanym — innymi słowy, w pewnym sensie przesuwanie ich z położenia oryginalnego do innego położenia. Filtru tego można użyć do wywołania efektu przesunięcia, wypaczenia lub nakrapiania. Lokalizacja i wielkość przemieszczenia nakładana na dany piksel jest określona wartością koloru na obrazie mapy przemieszczeń. Podczas pracy z filtrami, poza określeniem obrazu stanowiącego mapę użytkownik wskazuje również następujące wartości sterujące obliczaniem przemieszczenia z obrazu mapy:
W celu zrozumienia działania filtru mapy przemieszczeń należy zapoznać się z prostym przykładem. Poniższy kod opisuje załadowanie obrazu oraz niezwłocznie po jego załadowaniu wycentrowanie go na stole montażowym i nałożenie filtru mapy przemieszczeń, powodującego przemieszczenie pikseli na całym obrazie w poziomie w lewą stronę. 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);
Właściwości użyte do zdefiniowania tego przemieszczenia są następujące:
Ustawienia te powodują przesunięcie pikseli na filtrowanym obrazie o 250 pikseli na lewo. Kierunek (w stronę lewą lub prawą) oraz wielkość przesunięcia opierają się na wartości koloru pikseli na mapie obrazu. Jeśli chodzi o koncepcję, filtr odczytuje pojedynczo piksele na obrazie filtrowanym (lub co najmniej w obszarze podlegającym filtrowaniu danego obrazu, co w analizowanym wypadku oznacza wszystkie piksele) i wykonuje na każdym pikselu następujące operacje:
Ponieważ ani dla składnika y, ani dla skali y nie określono żadnych wartości, użyte zostały wartości domyślne (niepowodujące przemieszczenia) — dlatego obraz nie uległ przemieszczeniu w pionie. W przykładzie użyte zostało domyślne ustawienie trybu filtru, WRAP, tak że w miarę przesuwania się pikseli w lewo powstająca po prawej stronie pusta przestrzeń jest wypełniana pikselami, które „wypadły” z obrazu po jego lewej stronie. Z wartościami tymi można eksperymentować, sprawdzając, jakie przyniosą one efekty. Na przykład, dodając poniższy wiersz do fragmentu kodu dotyczącego ustawiania właściwości (przed wierszem loader.filters = [displacementMap]), można spowodować, że obraz będzie wyglądał, jak gdyby został rozsmarowany w poprzek stołu montażowego: displacementMap.mode = DisplacementMapFilterMode.CLAMP; Bardziej złożonym przykładem jest poniższy listing, korzystający z filtra mapy przemieszczeń do utworzenia efektu szkła powiększającego na obrazie: 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);
Pierwszy kod generuje dwa okręgi gradientowe, które połączone ze sobą, tworzą obraz mapy przemieszczeń. Czerwony okrąg odpowiada za przemieszczenie wzdłuż osi x (xyFilter.componentX = BitmapDataChannel.RED), natomiast niebieski — za przemieszczenie wzdłuż osi y (xyFilter.componentY = BitmapDataChannel.BLUE). Aby ułatwić czytelnikowi zrozumienie, jak wygląda mapa przemieszczeń, kod dodaje oryginalne okręgi, a także okręgi połączone, które pełnią rolę obrazu stanowiącego mapę, w dolnej części ekranu. ![]() Następuje załadowanie obrazu oraz, w wyniku ruchu muszą, nałożenie filtru przemieszczenia na fragment obrazu, nad którym znajduje się mysz. Okręgi gradientowe służące jako obraz mapy przemieszczeń powodują odrzucenie przemieszczonego obszaru daleko od wskaźnika myszy. Należy zauważyć, że szare obszary na obrazie mapy przemieszczeń nie powodują żadnego przemieszczenia. Kolor szary to 0x7F7F7F. Kanały niebieski i czerwony tego odcienia szarości dokładnie odpowiadają średniej odcieni tych kanałów kolorów, tak że w obszarze szarości obrazu mapy brak jest jakiegokolwiek przemieszczenia. Podobnie brak jest przemieszczeń w środkowej części okręgu. Mimo że kolor tam nie jest szary, kanały niebieski i czerwony tego koloru są identyczne z kanałem niebieskim i czerwonym średnioszarego, a ponieważ niebieski i czerwony są kolorami powodującymi przesunięcie, przesunięte to jest w tym miejscu zerowe. |
|