Recipe 8.13.
Applying a Filter to a Bitmap
Problem
You
want to apply a filter to a
BitmapData.
Solution
Use the applyFilter( ) method of the
BitmapData class, or add a filter to the filters array of
the enclosing Bitmap.
Discussion
As mentioned, there are two methods of applying
a filter to a bitmap. The first method is to use the
applyFilter( ) method directly on the BitmapData
itself. Like some of the other BitmapData methods, this
method is applied to one BitmapData, which is the
destination bitmap, and it can take another BitmapData as a
source bitmap:
destBmp.applyFilter(srcBmp, sourceRect, destPoint, filter);
-
The srcBmp is the bitmap file you want
to apply the filter to.
-
The sourceRect is the specific
rectangular area from the source bitmap that you want to apply the
filter to.
-
The destPoint parameter specifies
the upper lefthand point from which the pixels will be affected in
the destination bitmap.
-
The filter, of course, is an instance
of the BitmapFilter that you want to apply.
|
You can, of course, apply a filter using the
same bitmap as both source and destination. Doing so is considered
"destructive," not because it's a bad thing but because it
permanently changes the bitmap.
|
|
The values of each pixel are calculated based on
the original content and the filter parameters, and these values
overwrite the original pixel data. This is useful in a couple of
instances:
For example, the following code sets 100 random
pixels near the mouse position to white and then applies a default
blur filter. This is repeated on each frame, so the longer you
leave the mouse at one point, the brighter it gets. However, as you
move it around, the blur is repeatedly applied to those white
pixels, eventually fading them out. The result is a glowing
trail.
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.geom.Point;
public class FilteredBitmap extends Sprite {
private var _bitmap:BitmapData;
private var _image:Bitmap;
private var _blurFilter:BlurFilter;
public function FilteredBitmap( ) {
_bitmap = new BitmapData(stage.stageWidth, stage.stageHeight,
false, 0xff000000);
_image = new Bitmap(_bitmap);
addChild(_image);
_blurFilter = new BlurFilter( );
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(event:Event):void {
for(var i:int = 0; i < 100; i++) {
_bitmap.setPixel(mouseX + Math.random( ) * 20 - 10,
mouseY + Math.random( ) * 20 - 10,
0xffffffff);
}
_bitmap.applyFilter(_bitmap, _bitmap.rect, new Point( ), _blurFilter);
}
}
}
As you can see, the destructive method can be
quite creative. Contrast that to a nondestructive method that uses
two different bitmaps. One is the source bitmap and the other is
the destination. The method applies the filter to the bitmap data
in the source bitmap, and places the result in the destination
bitmap. It is nondestructive because the filter never alters the
original pixels in the source bitmap.
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.filters.BlurFilter;
import flash.events.Event;
import flash.geom.Point;
public class FilteredBitmap2 extends Sprite {
private var _bitmap:BitmapData;
private var _bitmap2:BitmapData;
private var _image:Bitmap;
private var _blurFilter:BlurFilter;
public function FilteredBitmap2( ) {
_bitmap = new BitmapData(stage.stageWidth, stage.stageHeight,
false, 0xff000000);
_bitmap2 = new BitmapData(stage.stageWidth, stage.stageHeight,
false, 0xff000000);
_image = new Bitmap(_bitmap);
addChild(_image);
_blurFilter = new BlurFilter( );
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(event:Event):void {
for(var i:int = 0; i < 100; i++) {
_bitmap2.setPixel(mouseX + Math.random( ) * 20 - 10,
mouseY + Math.random( ) * 20 - 10,
0xffffffff);
}
_bitmap.applyFilter(_bitmap2, _bitmap.rect, new Point( ), _blurFilter);
}
}
}
The other method of applying a filter to a
bitmap is to add it to the filters property of the Bitmap
that holds a BitmapData. This is another nondestructive
method of applying a filter, as the pixel data in the
BitmapData is not touched. The filter is only applied to the
Bitmap that wraps the BitmapData. The following code
shows this method in action.
package {
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.filters.BlurFilter;
import flash.events.Event;
public class FilteredBitmap3 extends Sprite {
private var _bitmap:BitmapData;
private var _image:Bitmap;
public function FilteredBitmap3( ) {
_bitmap = new BitmapData(stage.stageWidth, stage.stageHeight,
false, 0xff000000);
_image = new Bitmap(_bitmap);
addChild(_image);
_image.filters = [new BlurFilter( )];
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(event:Event):void {
for(var i:int = 0; i < 100; i++) {
_bitmap.setPixel(mouseX + Math.random( ) * 20 - 10,
mouseY + Math.random( ) * 20 - 10,
0xffffffff);
}
}
}
}
Here you can see that the filter is applied only
the one time. The drawn pixels are slightly blurred, but they don't
continuously blur until they fade out. If at some point you deleted
the filter from the Bitmap, you would see that the white
pixels are still perfectly sharp, as the blur was only applied to
the container, not the actual bitmap data.
See Also
Recipes 8.12,
8.14,
and 8.15
for other ways to manipulate the content in a bitmap.
|