package
{
    
    /*
    ColorCorrectionFilter for Flash Player 10  
    by Petri Leskinen, in Finland, November 2008
    http://pixelero.wordpress.com/
    */
    
    import flash.filters.ColorMatrixFilter;
    import flash.geom.Vector3D;
    import flash.geom.Matrix3D;
    
    public class ColorCorrectionFilter
    {
        /*    vectors pointing from origin
            c ~ color
            g ~ grayscale    */
            
        protected var c:Vector3D;
        protected var g:Vector3D;
        
        public var filter:ColorMatrixFilter;
        
        static protected const radToDeg:Number = 180.0/Math.PI;
        
        public function ColorCorrectionFilter(_oldColor:uint = 0xF0E0D0, _newColor:uint = 0xFFFFFF) {
            c = new Vector3D();
            g = new Vector3D();
            filter = new ColorMatrixFilter();
            oldColor = _oldColor;
            newColor = _newColor;
            
        }
        
        public function set oldColor (value:uint) :void {
            c = ColorCorrectionFilter.uintToVector3D(value);
            updateFilter();
        }
        
        public function get oldColor () :uint {
            return int(c.z) | (int(c.y)<<8) | (int(c.x)<<16);
        }
        
        public function set newColor (value:uint) :void {
            g = ColorCorrectionFilter.uintToVector3D(value);
            updateFilter();
        }
        public function get newColor () :uint {
            return int(g.z) | (int(g.y)<<8) | (int(g.x)<<16);
        }
        protected function updateFilter() :void {
                
                /*    normal vector for a plane 
                    by three points, the origin(0,0,0), c and g    */
                            
                var normal:Vector3D = c.crossProduct(g);
                normal.normalize();
                
                /*     theta, the angle - or rotation -
                    between c and g,
                    we need the value in degrees    */
                
                var theta:Number = Vector3D.angleBetween(c,g) *ColorCorrectionFilter.radToDeg;
                
                /*    create a new matrix3D,
                    and apply such a rotation that 
                    point c transformed to the diagonal 'greyscale' line
                    from (0,0,0) to (255,255,255),
                    where r = g = b            */
                
                var mtrx:Matrix3D = new Matrix3D();
                mtrx.prependRotation(-theta, normal);
                
                filter = new ColorMatrixFilter( [
                //filter.array = [
                    //    read the output array from rawData in mtrx:
                     //    red component, alpha factor 0.0, [3] = translation
                    mtrx.rawData[0],mtrx.rawData[1],mtrx.rawData[2], 0.0, mtrx.rawData[3], 
                    //    green component
                    mtrx.rawData[4],mtrx.rawData[5],mtrx.rawData[6], 0.0, mtrx.rawData[7],
                    //    blue component
                    mtrx.rawData[8],mtrx.rawData[9],mtrx.rawData[10], 0.0, mtrx.rawData[11],
                    //    alpha, no change
                    0.0,            0.0,            0.0,            1.0,    0.0
                    ] ); 
                    
                    
            }
            
        protected static function uintToVector3D(value:uint):Vector3D {
                /*    convert the color value in uint 0xRRGGBB
                //    to a 3Dvector in rgb-colorspace
                //    values (0.0,0.0,0.0) - (r,g,b)- (255.0,255.0,255.0)
                */
                return new Vector3D(
                    (value>>16) &0xFF,  // red  = x
                    (value>>8)&0xFF, // green = y
                    value&0xFF ); //  blue = z
                
        }
    }
}