topical media & game development
#filter-wood.ax
#filter-wood.ax
[swf]
flex
package {
author: Joel May
www.connectedpixel.com
All original source code listed here is licensed under a Creative Commons License.
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.BlurFilter;
import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;
import flash.geom.ColorTransform;
////////////////////////////////////////////////////////////////////
// Renders a wood texture to a bitmap. Uses perlin noise and the folumula
// pixval = fraction(nTreeRings * perlin(x,y))
////////////////////////////////////////////////////////////////////
class @ax-filter-wood {
private var _baseX :Number = 400;
private var _baseY :Number = 120;
private var _nOctaves :Number = 1;
private var _randomSeed :Number = 128;
private var _bTile :Boolean = false;
private var _bFractalNoise :Boolean = false;
private var _nGrainLayers :Number = 15;
private var _blurX :Number = 5;
private var _blurY :Number = 5;
private var _rgb0:Number = 0xaa5522;
private var _rgb1:Number = 0xee9922;
private var _identityMatrix:Matrix;
private var _identityColorTrans:ColorTransform;
private var _woodColorFilter:ColorMatrixFilter;
private var _blurFilter:BlurFilter;
private function invalidateWoodColorFilter():Void
{
delete _woodColorFilter;
_woodColorFilter = undefined;
}
private function invalidateBlurFilter():Void
{
delete _blurFilter;
_blurFilter = undefined;
}
////////////////////////////////////////////////////////////////
// Properties.
public function set perlinBaseX(bx:Number):Void {
if (isNaN(bx)) return;
if (bx < 3) bx = 3;
if (bx > 1000) bx = 1000;
_baseX = bx;
}
public function get perlinBaseX():Number { return _baseX; }
public function set perlinBaseY(by:Number):Void {
if (isNaN(by)) return;
if (by < 3) by = 3;
if (by > 1000) by = 1000;
_baseY = by;
}
public function get perlinBaseY():Number { return _baseY; }
public function set octaves(nOct:Number):Void { _nOctaves = nOct; }
public function get octaves():Number { return _nOctaves; }
public function set grainLayers(nLayers:Number):Void { _nGrainLayers = nLayers; }
public function get grainLayers():Number { return _nGrainLayers; }
public function set rgb0(rgb:Number):Void {
_rgb0 = rgb; invalidateWoodColorFilter();
}
public function get rgb0():Number { return _rgb0; }
public function set rgb1(rgb:Number):Void {
_rgb1 = rgb; invalidateWoodColorFilter();
}
public function get rgb1():Number { return _rgb1; }
public function set seed(s:Number):Void { _randomSeed = s; }
public function get seed():Number { return _randomSeed; }
public function set tileable(bTile:Boolean):Void { _bTile = bTile; }
public function get tileable():Boolean { return _bTile; }
public function set fractalNoise(bFractal:Boolean):Void { _bFractalNoise = bFractal; }
public function get fractalNoise():Boolean { return _bFractalNoise; }
public function @ax-filter-wood()
{
_identityMatrix = new Matrix();
_identityColorTrans = new ColorTransform();
}
//////////////////////////////////////////////////////////////////
// Convenience function. Returns a bitmap of the desired
// size using the current wood settings.
/////////////////////////////////////////////////////////////////
public function createBitmap(w:Number,h:Number):BitmapData
{
var wood_bmp:BitmapData = new BitmapData(w, h, false, 0x000000);
render(wood_bmp);
return wood_bmp;
}
//////////////////////////////////////////////////////////////////
// Render the wood grain onto the bitmap using the current property
// values.
// buffer0_bmp and buffer1_bmp are optional. If they are not supplied
// temporary bitmaps will be created. They MUST have the same
// width and height as the destination bmp.
/////////////////////////////////////////////////////////////////
public function render(bmp:BitmapData, buffer0_bmp:BitmapData, buffer1_bmp:BitmapData):Void
{
var w:Number = bmp.width;
var h:Number = bmp.height;
// Will hold perlin noise.
var srcNoise_bmp:BitmapData = (buffer0_bmp != undefined) ? buffer0_bmp :
new BitmapData(w, h, false, 0xffffffff);
var tmp_bmp:BitmapData = (buffer1_bmp != undefined) ? buffer1_bmp :
new BitmapData(w, h, false, 0xffffffff);
// channelOptions - 1 - Red only
// grayscale - false
srcNoise_bmp.perlinNoise(_baseX,_baseY,_nOctaves,_randomSeed,_bTile,_bFractalNoise,1,false);
// Needed in some of the following flash api calls.
var rect:Rectangle = new Rectangle(0,0,w,h);
var origin:Point = new Point(0,0);
// For each tree ring.
for (var iLayer:Number = 0 ; iLayer < _nGrainLayers ; iLayer++){
// After multiplying, the signal needs to be shifted into the
// 0 to 255 range.
var offset:Number = - iLayer * 256;
// Amplify and shift the pixels.
var matrix:Array = [_nGrainLayers, 0, 0, 0, offset,
0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
0, 0, 0, 1, 0 ];
var filter:BitmapFilter = new ColorMatrixFilter(matrix);
tmp_bmp.applyFilter(srcNoise_bmp,rect,origin,filter);
// Set the brightest to be black. Following layers will write
// only on the black.
tmp_bmp.threshold(tmp_bmp, rect, origin, "==", 0x00ff0000, 0xff000000, 0x00ff0000, false);
// Copy the tmp on to the dest bitmap.
var blend:Object = 5; //lighten
bmp.draw(tmp_bmp, _identityMatrix, _identityColorTrans, blend);
}
// Don't need the temporary bitmaps anymore
if (buffer1_bmp == undefined){
tmp_bmp.dispose();
}
if (buffer0_bmp == undefined){
srcNoise_bmp.dispose();
}
// Change it from black and red to the desired colors.
bmp.applyFilter(bmp,rect, origin, getWoodColorFilter());
// Blur it to remove the jaggies.
bmp.applyFilter(bmp,rect,origin,getBlurFilter());
}
/////////////////////////////////////////////////////////////////
// Create a filter that will lessen the jaggies. The threshold() call
// creates jaggies that are pretty bad. This basically solves the
// problem.
/////////////////////////////////////////////////////////////////
private function getBlurFilter():BlurFilter
{
if (_blurFilter != undefined){
return _blurFilter;
}
_blurFilter = new BlurFilter(_blurX,_blurY,1);
return _blurFilter;
}
/////////////////////////////////////////////////////////////////
// Map the black to red colors to the desired wood colors.
/////////////////////////////////////////////////////////////////
private function getWoodColorFilter():ColorMatrixFilter
{
if (_woodColorFilter != undefined){
return _woodColorFilter;
}
// Apply the desired colors to the bitmap.
var r0:Number = (_rgb0 >> 16) & 0xff;
var g0:Number = (_rgb0 >> 8 ) & 0xff;
var b0:Number = _rgb0 & 0xff;
var r1:Number = (_rgb1 >> 16) & 0xff;
var g1:Number = (_rgb1 >> 8 ) & 0xff;
var b1:Number = _rgb1 & 0xff;
var woodColor:Array = [(r1-r0)/255, 0, 0, 0, r0,
(g1-g0)/255, 0, 0, 0, g0,
(b1-b0)/255, 0, 0, 0, b0,
0 , 0, 0, 1, 0 ];
_woodColorFilter= new ColorMatrixFilter(woodColor);
return _woodColorFilter;
}
}
}
(C) Æliens
27/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.