Saturday, July 30, 2011

Filter.as - as3-classes - my collection of useful as3 classes - Google Project Hosting

Filter.as - as3-classes - my collection of useful as3 classes - Google Project Hosting


package org.lzyy.util {
import flash.display.*;
import flash.geom.*;
import flash.filters.*;

/**
* as.Filter
*
* as3.Filter class includes methods generate variety of filters for image processing.
*/
public class Filter
{
/**
* Generate the DisplacementMapFilter for twirling effect.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Filter.twirlFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* You can also apply the filter specified region:
*
* var region:Rectangle = new Rectangle(100, 100, 100, 100);
* var filter:DisplacementMapFilter = Filter.twirlFilter(bmd, rect);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @params rotation Number The max amount to rotate, in radius.
* Default is Math.PI / 2.
*
* @return DisplacementMapFilter Filter to apply twirl effect
*/
static public function twirlFilter(source:BitmapData, region:Rectangle=null,
rotation:Number=0):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
rotation ||= Math.PI / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var radius:Number = Math.min(region.width, region.height) / 2;
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var dr:Number = radius - Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(dr > 0) {
var angle:Number = dr / radius * rotation;
var dx:Number = xcoord * Math.cos(angle) - ycoord * Math.sin(angle) - xcoord;
var dy:Number = xcoord * Math.sin(angle) + ycoord * Math.cos(angle) - ycoord;
var blue:int = 0x80 + Math.round(dx / width * 0xff);
var green:int = 0x80 + Math.round(dy / height * 0xff);
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.IGNORE);
}

/**
* Generate the BitmapData which applied mirror effect.
*
* You can create the mirrored BitmapData is as follows:
*
* var bmd = new BitmapData(video.width, video.height, false);
* bmd.draw(video);
* var mirroredBmd = Filter.mirror(bmd);
*
* @params source BitmapData The input bitmap data to apply the mirror effect.
* @params region Rectangle The region to apply the twirling effect. Default is entire region.
* @return BitmapData BitmapData which applied the mirror effect
*/
static public function mirror(source:BitmapData):BitmapData
{
var bmd:BitmapData = new BitmapData(source.width, source.height, false);
var halfWidth:int = Math.round(source.width / 2);
source.lock();
bmd.copyPixels(source, new Rectangle(0, 0, halfWidth, source.height), new Point(0,0));
for(var i:int=0;i<source.height;++i) {
for(var j:int=0;j<halfWidth;++j) {
bmd.setPixel32(halfWidth + j, i, source.getPixel32(halfWidth - j, i));
}
}
source.unlock();
return bmd;
}

/**
* Generate the DisplacementMapFilterMode for pinch effect.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Filter.pinchFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* You can also apply the filter specified region:
*
* var region:Rectangle = new Rectangle(100, 100, 100, 100);
* var amount:Number = 0.5;
* var filter:DisplacementMapFilter = Filter.pinchFilter(bmd, rect, amount);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @params amount Number Amount of pinch. (-1 <= x <= 1)
* Default is 0.35.
*/
static public function pinchFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.35):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
var radius:Number = Math.min(region.width, region.height) / 2;
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(d < radius) {
var t:Number = d == 0 ? 0 : Math.pow(Math.sin(Math.PI / 2 * d / radius), -amount);
var dx:Number = xcoord * (t - 1) / width;
var dy:Number = ycoord * (t - 1) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for photic tunnel effect.
* Photic tunnel effect is as same as effect of Photo Booth application in Mac OS.
*
* You can apply the filter is as follows:
*
* var bmd:BitmapData = new BitmapData(width, height, false);
* var filter:DisplacementMapFilter = Filter.pinchFilter(bmd);
* bmd.draw(video);
* bmd.applyFilter(bmd, bmd.rect, new Point(0, 0), filter);
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params region Rectangle The region to apply the twirling effect.
* @return DisplacementMapFilter Filter to apply photic tunnel effect.
*/
static public function photicTunnelFilter(source:BitmapData, region:Rectangle=null):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
region ||= new Rectangle(0, 0, width, height);
var centerX:int = region.x + region.width / 2;
var centerY:int = region.y + region.height / 2;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var radius:Number = Math.min(region.width, region.height) / 2;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(radius < d) {
var angle:Number = Math.atan2(Math.abs(ycoord), Math.abs(xcoord));
var dx:Number = (xcoord > 0? -1 : 1) * (d - radius) * Math.cos(angle) / width;
var dy:Number = (ycoord > 0? -1 : 1) * (d - radius) * Math.sin(angle) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for bulge effect.
* Bulge effect is wrapper of pinchFilter method.
*
* @params source BitmapData The input bitmap data to apply the effect.
* @params region Rectangle The region to apply the bulge effect.
* @params amount Number Amount of bulge. (0 <= x <= 1)
* @return DisplacementMapFilter The filter to apply bulge effect.
*/
static public function bulgeFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.5):DisplacementMapFilter
{
// wrapper method of pinchFilter
return pinchFilter(source, region, Math.min(-amount, -1));
}
/**
* Generate the DisplacementMapFilter for squeeze effect.
* Dent effect is wrapper of pinchFilter method.
*
* @params source BitmapData The input bitmap data to apply the effect.
* @params region Rectangle The region to apply the bulge effect
* @params amount Number Amount of squeeze. (0 <= x <= 1)
*/
static public function squeezeFilter(source:BitmapData, region:Rectangle=null,
amount:Number=0.5):DisplacementMapFilter
{
// wrapper method of bulge filter
return pinchFilter(source, region, amount);
}

/**
* Generate the DisplacementMapFilter for fisheye effect.
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params amount Number Amount of fisheye (0 <= x <= 1)
* @return DisplacementMapFilter The filter to apply the fisheye effect.
*/
static public function fisheyeFilter(source:BitmapData, amount:Number=0.8):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var centerX:int = width / 2;
var centerY:int = height / 2;
var radius:Number = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2));
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var d:Number = Math.sqrt(xcoord * xcoord + ycoord * ycoord);
if(d < radius) {
var t:Number = d == 0 ? 0 : Math.pow(Math.sin(Math.PI / 2 * d / radius), amount);
var dx:Number = xcoord * (t - 1) / width;
var dy:Number = ycoord * (t - 1) / height;
var blue:int = 0x80 + dx * 0xff;
var green:int = 0x80 + dy * 0xff;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}

/**
* Generate the DisplacementMapFilter for strech effect.
*
* @params source BitmapData The input bitmap data to apply the twirling effect.
* @params amount Number Amount of strech (0 <= x <= 1), default is 0.6;
* @return DisplacementMapFilter The filter to apply the strech effect.
*/
static public function strechFilter(source:BitmapData, amount:Number=0.6):DisplacementMapFilter
{
var width:int = source.width;
var height:int = source.height;
var dbmd:BitmapData = new BitmapData(width, height, false, 0x8080);
var centerX:int = width / 2;
var centerY:int = height / 2;
var vregion:Rectangle = new Rectangle(0, 0 , width / 3, height);
var hregion:Rectangle = new Rectangle(0, 0, width, height / 3);
var blue:int;
var green:int;
for(var y:int=0;y<height;++y) {
var ycoord:int = y - centerY;
for(var x:int=0;x<width;++x) {
var xcoord:int = x - centerX;
var dx:int = (Math.abs(xcoord) < vregion.width)?
xcoord * (Math.pow(Math.abs(xcoord) / vregion.width, amount) - 1) : 0x0;
var dy:int = (Math.abs(ycoord) < hregion.height)?
ycoord * (Math.pow(Math.abs(ycoord) / hregion.height, amount) - 1) : 0x0;
blue = 0x80 + 0xff * dx / width;
green = 0x80 + 0xff * dy / height;
dbmd.setPixel(x, y, green << 8 | blue);
}
}
return new DisplacementMapFilter(dbmd,
new Point(0, 0),
BitmapDataChannel.BLUE,
BitmapDataChannel.GREEN,
width,
height,
DisplacementMapFilterMode.CLAMP);
}
}
}

No comments: