topical media & game development
actionscript-book-FilterWorkbench-com-example-programmingas3-filterWorkbench-ColorMatrixFactory.ax
actionscript-book-FilterWorkbench-com-example-programmingas3-filterWorkbench-ColorMatrixFactory.ax
[swf]
flex
package
{
//import com.example.programmingas3.filterWorkbench.IFilterFactory;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.filters.BitmapFilter;
import flash.filters.ColorMatrixFilter;
// ------- Events -------
[Event(name="change", type="flash.events.Event")]
public class @ax-actionscript-book-FilterWorkbench-com-example-programmingas3-filterWorkbench-ColorMatrixFactory extends EventDispatcher implements actionscript_book_FilterWorkbench_com_example_programmingas3_filterWorkbench_IFilterFactory
{
// ------- Private vars -------
private var _filter:ColorMatrixFilter;
private var _paramString:String;
private var _matrix:Array;
// ------- Constructor -------
public function @ax-actionscript-book-FilterWorkbench-com-example-programmingas3-filterWorkbench-ColorMatrixFactory(matrix:Array = null)
{
if (matrix == null)
{
resetMatrix();
}
else
{
_matrix = matrix;
}
_filter = new ColorMatrixFilter(_matrix);
}
// ------- IFilterFactory implementation -------
public function getFilter():BitmapFilter
{
return _filter;
}
public function getCode():String
{
var result:String = "";
result += "import flash.filters.ColorMatrixFilter;\n";
result += "\n";
result += "var matrix:Array = [";
for (var i:int = 0; i < 20; i++)
{
if (i > 0)
{
result += ", ";
}
if (i % 5 == 0)
{
result += "\n\t\t\t";
}
result += _matrix[i].toString();
}
result += "\n\t\t\t];\n";
result += "\n";
result += "var colorMatrix:ColorMatrixFilter;\n";
result += "colorMatrix = new ColorMatrixFilter(matrix);\n";
result += "\n";
result += "myDisplayObject.filters = [colorMatrix];";
return result;
}
// ------- Public properties -------
public function get matrix():Array
{
return _matrix;
}
// ------- Public methods -------
public function modifyFilterBasic(brightness:Number, contrast:Number, saturation:Number, hue:Number):void
{
// calculate the combined matrix using the preset values
resetMatrix();
setHue(hue);
setSaturation(saturation);
setContrast(contrast);
setBrightness(brightness);
_filter = new ColorMatrixFilter(_matrix);
dispatchEvent(new Event(Event.CHANGE));
}
public function modifyFilterCustom(matrix:Array = null):void
{
if (matrix == null)
{
resetMatrix();
}
else
{
_matrix = matrix;
}
_filter = new ColorMatrixFilter(_matrix);
dispatchEvent(new Event(Event.CHANGE));
}
// ------- Color adjustments -------
private function resetMatrix():void
{
_matrix = [1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0];
}
// Color matrix algorithms derived from:
// Haeberli, Paul (1993) "Matrix Operations for Image Processing."
// Graphica Obscura: http://www.graficaobscura.com/matrix/index.html
// takes a brightness value between -100 and 100
private function setBrightness(value:Number):void
{
// convert the value to a percentage of 255
var brightness:Number = (value / 100) * 255;
var matrix:Array = [1, 0, 0, 0, brightness,
0, 1, 0, 0, brightness,
0, 0, 1, 0, brightness,
0, 0, 0, 1, 0];
_matrix = mMultiply(_matrix, matrix);
}
// takes a contrast value between -100 and 100
private function setContrast(value:Number):void
{
var base:Number = value / 100;
var multiplier:Number = 1 + ((value > 0) ? 4 * base : base);
var offset:Number = (-128 * base) * ((value > 0) ? 5 : 1);
var matrix:Array = [multiplier, 0, 0, 0, offset,
0, multiplier, 0, 0, offset,
0, 0, multiplier, 0, offset,
0, 0, 0, 1, 0];
_matrix = mMultiply(_matrix, matrix);
}
// takes a saturation value between -100 and 100
private function setSaturation(value:Number):void
{
var saturation:Number = 1 + ((value > 0) ? 3 * (value / 100) : (value / 100));
// RGB to Luminance conversion constants by Charles A. Poynton:
// http://www.faqs.org/faqs/graphics/colorspace-faq/
var rWeight:Number = 0.212671;
var gWeight:Number = 0.715160;
var bWeight:Number = 0.072169;
var baseSat:Number = 1 - saturation;
var rSat:Number = (baseSat * rWeight) + saturation;
var r:Number = baseSat * rWeight;
var gSat:Number = (baseSat * gWeight) + saturation;
var g:Number = baseSat * gWeight;
var bSat:Number = (baseSat * bWeight) + saturation;
var b:Number = baseSat * bWeight;
var matrix:Array = [rSat, g, b, 0, 0,
r, gSat, b, 0, 0,
r, g, bSat, 0, 0,
0, 0, 0, 1, 0];
_matrix = mMultiply(_matrix, matrix);
}
// takes a hue value (an angle) between -180 and 180 degrees
private function setHue(value:Number):void
{
var angle:Number = value * Math.PI / 180;
var c:Number = Math.cos(angle);
var s:Number = Math.sin(angle);
var lumR:Number = 0.213;
var lumG:Number = 0.715;
var lumB:Number = 0.072;
var matrix:Array = [lumR + (c * (1 - lumR)) + (s * (-lumR)), lumG + (c * (-lumG)) + (s * (-lumG)), lumB + (c * (-lumB)) + (s * (1 - lumB)), 0, 0,
lumR + (c * (-lumR)) + (s * 0.143), lumG + (c * (1 - lumG)) + (s * 0.14), lumB + (c * (-lumB)) + (s * (-0.283)), 0, 0,
lumR + (c * (-lumR)) + (s * (-(1 - lumR))), lumG + (c * (-lumG)) + (s * lumG), lumB + (c * (1 - lumB)) + (s * lumB), 0, 0,
0, 0, 0, 1, 0];
_matrix = mMultiply(_matrix, matrix);
}
// Performs matrix multiplication between two 4x5 matrices
private static function mMultiply(m1:Array, m2:Array):Array
{
var result:Array = new Array(20);
for (var row:int = 0; row < 19; row += 5)
{
for (var col:int = 0; col < 5; col++)
{
var cell:Number = (m1[row] * m2[col]) + (m1[row + 1] * m2[col + 5]) + (m1[row + 2] * m2[col + 10]) + (m1[row + 3] * m2[col + 15]);
if (col == 4)
{
cell += m1[row + 4];
}
result[row + col] = cell;
}
}
return result;
}
}
}
(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.