In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

James SharpQUTforked from: [WebCam] Manic Monday

Forked from: [WebCam] Manic Monday
説明:http://aquioux.blog48.fc2.com/blog-entry-710.html
@author Aquioux(Yoshida, Akio)
&author james sharp
/**
 * Copyright jamessharp89 ( http://wonderfl.net/user/jamessharp89 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/yPLD
 */

// forked from Aquioux's [WebCam] Manic Monday
package {
    import flash.display.Sprite;
    //import net.hires.debug.Stats;
    [SWF(width = "465", height = "465", frameRate = "30", backgroundColor = "#FF0000")]
    
    /**
     * Forked from: [WebCam] Manic Monday
     * http://aquioux.blog48.fc2.com/blog-entry-710.html
     * @author james sharp
     */
     
     //modify lines: 101,129,154,219,265-8
    public class Main extends Sprite {
        public function Main():void {
            //Wonderfl.capture_delay(30);

            // model
            try {
                var model:Model = new Model(stage);
            } catch (err:Error) {
                trace(err.message);
                return;
            }
            
            // view
            var view:View = new View(model);
            addChild(view);
            
            // controller
            var controller:Controller = new Controller(model);
            
            addChild(controller);  
        }
    }
}
    import flash.display.BitmapData;
    import flash.display.Stage;
    import flash.events.ActivityEvent;
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.media.Camera;
    import flash.media.Video;
    
    class Model extends EventDispatcher {
        
        public function get data():BitmapData { return _data; }
        private var _data:BitmapData;

        private var stage_:Stage;
        private var cameraWidth_:uint;
        private var cameraHeight_:uint;
        private var camera_:Camera;
        private var video_:Video;
        private var matrix_:Matrix;
        private var smooth_:Smooth;            
        private var grayscale_:GrayScale;    
        private var nega_:Negative;            
        private var binarize_:Binarize;        
        private var divider_:SubDivider;    
        private var gray_:BitmapData;
        private var rect_:Rectangle;
        private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;
        
        private var isNegative_:Boolean = false;
        
        public function Model(stage:Stage, cw:uint = 0, ch:uint = 0) {
            
            stage_ = stage;
            var w:uint = stage_.stageWidth;
            var h:uint = stage_.stageHeight;
            cameraWidth_  = (cw == 0) ? w : cw;
            cameraHeight_ = (ch == 0) ? h : ch;

            _data = new BitmapData(w, h, true, 0x00000000);

            gray_ = new BitmapData(w, h, false, 0x000000);
            rect_ = _data.rect;
           
            var tx:uint = (w - cameraWidth_)  / 2 + cameraWidth_;
            var ty:uint = (h - cameraHeight_) / 2;
            matrix_ = new Matrix( -1, 0, 0, 1, tx, ty);
            
            camera_ = Camera.getCamera();
            if (camera_) {
                
                camera_.setMode(cameraWidth_, cameraHeight_, stage_.frameRate);
                
                video_ = new Video(cameraWidth_, cameraHeight_);
                video_.attachCamera(camera_);
                
                camera_.addEventListener(ActivityEvent.ACTIVITY, activeHandler);
            } else {
                throw new Error("an error has occured! Is your webcam connected?");
            }
            
            smooth_ = new Smooth();            
            smooth_.strength = 0;  //change strength for more solid shaped. eg + 50 is very solid. originally 4
            grayscale_ = new GrayScale();   
            nega_ = new Negative();           
            binarize_ = new Binarize();        
            binarize_.auto = true;
            divider_ = new SubDivider();    
        }
        
        public function notifyFromController():void {
            isNegative_ = !isNegative_;
        }
        
        private function activeHandler(e:ActivityEvent):void {
            camera_.removeEventListener(ActivityEvent.ACTIVITY, arguments.callee);
            stage_.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
        }
        
        private function enterFrameHandler(event:Event):void {
            _data.draw(video_, matrix_);
            
            smooth_.applyEffect(_data);       
            grayscale_.applyEffect(_data);    
            gray_.copyPixels(_data, rect_, ZERO_POINT);
            if (isNegative_) nega_.applyEffect(gray_);    
            binarize_.applyEffect(gray_);   
            _data.fillRect(rect_, 0x00000000);
            //size of smalest block. change from around 5-25 where 2 small blocks, 20 solid. originally 10
            //has an effect on the colours
            divider_.applyEffect(rect_, gray_, _data, 8, 8, binarize_.threshold);

            dispatchEvent(new Event(Event.CHANGE));
        }
    }

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.events.Event;
    import flash.filters.DropShadowFilter;
    import flash.geom.Point;
    import flash.geom.Rectangle;
  
    class View extends Bitmap {
   
        public function set model(value:Model):void { _model = value; }
        private var _model:Model;
       
        private var filter:DropShadowFilter;
        

        public function View(model:Model) {
            _model = model;
            _model.addEventListener(Event.CHANGE, changeHandler);
//play around with this (size, angle, colour, alpha, xblur, yblur)
            filter = new DropShadowFilter(5, 45, 0x666666, 1, 8, 8);//changes the colour of the shadow around the blocks
            filters = [filter];
        }
        private function changeHandler(e:Event):void {
            bitmapData = _model.data;
        }
    }

    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    
    class Controller extends Sprite {
        
        public function set model(value:Model):void { _model = value; }
        private var _model:Model;
        
        public function Controller(model:Model) {
            _model = model;
            addEventListener(Event.ADDED_TO_STAGE, addToStageHandler);
        }
        
        private function addToStageHandler(e:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, arguments.callee);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
        }
        private function keyDownHandler(e:KeyboardEvent):void {
            if (e.keyCode == 82) _model.notifyFromController();    // "r" invert the light
        }
    }

    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.geom.Rectangle;
    import frocessing.color.ColorHSV;

    class SubDivider {
      //create the rectangle
        private var nextRect_:Rectangle = new Rectangle();    
        private var drawRect_:Rectangle = new Rectangle();    
        
        private const GET_BRIGHTNESS:Function = EffectorUtils.getSumOfBrightness1;
        
        public var hsv_:ColorHSV = new ColorHSV();
        
        public function SubDivider() {
        }
        //here we create affects to the rectagles size etc
        public function applyEffect(rect:Rectangle, gray:BitmapData, canvas:BitmapData, divideThreshold:uint, minSize:uint, drawThreshold:uint, callInner:Boolean = false):void {
            
            if (!callInner) hsv_.h = 0;
            
            var isDivide:Boolean = rect.width > minSize && rect.height > minSize;
            
            var numOfPixel:uint = rect.width * rect.height;
            
            var hist:Vector.<Vector.<Number>> = gray.histogram(rect);

            if (isDivide) {
                
                var deviation:Number = getStandardDeviation(hist[0], numOfPixel);
                if (deviation > divideThreshold) {
                    
                    //size of shapes..change for great results
                    var nextWidth1:uint  = rect.width  /2; //between 1.5 and 5
                    var nextHeight1:uint = rect.height /2;//between 1.5 and 5
                    var nextWidth2:uint  = (rect.width  - nextWidth1) * 1;//*1.2;
                    var nextHeight2:uint = (rect.height - nextHeight1) * 1;//*1.2;
                    var left:Number = rect.x;
                    var top:Number  = rect.y;
                    var center:Number = left + nextWidth1;
                    var middle:Number = top  + nextHeight1;
                    var xs:Vector.<uint> = Vector.<uint>([left, center, left, center]);
                    var ys:Vector.<uint> = Vector.<uint>([top, top, middle, middle]);
                    var ws:Vector.<uint> = Vector.<uint>([nextWidth1, nextWidth2, nextWidth1, nextWidth2]);
                    var hs:Vector.<uint> = Vector.<uint>([nextHeight1, nextHeight1, nextHeight2, nextHeight2]);
                    
                    for (var i:int = 0; i < 4; i++) {
                        nextRect_.x = xs[i];
                        nextRect_.y = ys[i];
                        nextRect_.width  = ws[i];
                        nextRect_.height = hs[i];
                        applyEffect(nextRect_, gray, canvas, divideThreshold, minSize, drawThreshold, true);
                    }
                } else {
                    isDivide = false;
                }
            }
            if (!isDivide) draw(rect, hist[0], numOfPixel, canvas, drawThreshold);
        }

        private function getStandardDeviation(hist:Vector.<Number>, numOfPixel:uint):Number {
            var average:Number = hist[255] * 255 / numOfPixel;
            
            var diff:Number = 0;
            var sum:uint = 0;
            diff = -average;
            sum += diff * diff * hist[0];
            diff = 255 - average;
            sum += diff * diff * hist[255];
            
            return Math.sqrt(sum / numOfPixel);
        }
        
        private function draw(rect:Rectangle, hist:Vector.<Number>, numOfPixel:uint, canvas:BitmapData, threshold:uint):void {
            var sum:uint = GET_BRIGHTNESS(hist);
            var brightness:uint = sum / numOfPixel;
            if (brightness < threshold) {
                drawRect_.x = rect.x + 1;
                drawRect_.y = rect.y + 1;
                drawRect_.width  = rect.width  - 2; //distance between blocks, originally 2
                drawRect_.height = rect.height - 2;
                canvas.fillRect(drawRect_, hsv_.value32);
                hsv_.h += 0.3; //speed and rate of block changing colour
            }
        }
    }

    import flash.display.BitmapData;

    interface IEffector {
        function applyEffect(value:BitmapData):BitmapData;
    }

    import flash.geom.Point;

    class EffectorUtils {

        static public const ZERO_POINT:Point = new Point(0, 0);

        static public function getAverageOfBrightness1(hist:Vector.<Number>):uint {
            var sum:uint = 0;
            var numOfPixel:uint = 0;
            for (var i:int = 0; i < 256; i++) {
                sum        += i * hist[i];
                numOfPixel += hist[i];
            }
            return sum / numOfPixel >> 0;
        }
     
        static public function getAverageOfBrightness3(hist:Vector.<Vector.<Number>>):Vector.<uint> {
            var rSum:uint = 0;
            var gSum:uint = 0;
            var bSum:uint = 0;
            var numOfPixel:uint = 0;
            for (var i:int = 0; i < 256; i++) {
                rSum += i * hist[0][i];
                gSum += i * hist[1][i];
                bSum += i * hist[2][i];
                numOfPixel += hist[0];
            }
            return Vector.<uint>([rSum / numOfPixel >> 0, gSum / numOfPixel >> 0, bSum / numOfPixel >> 0]);
        }

        static public function getSumOfBrightness1(hist:Vector.<Number>):uint {
            var sum:uint = 0;
            for (var i:int = 0; i < 256; i++) {
                sum += i * hist[i];
            }
            return sum;
        }
  
        static public function getSumOfBrightness3(hist:Vector.<Vector.<Number>>):Vector.<uint> {
            var rSum:uint = 0;
            var gSum:uint = 0;
            var bSum:uint = 0;
            for (var i:int = 0; i < 256; i++) {
                rSum += i * hist[0][i];
                gSum += i * hist[1][i];
                bSum += i * hist[2][i];
            }
            return Vector.<uint>([rSum, gSum, bSum]);
        }
    }

    import flash.display.BitmapData;
    import flash.filters.BitmapFilterQuality;
    import flash.filters.BlurFilter;
    import flash.geom.Point;
    
    class Smooth implements IEffector {
       
        public function set strength(value:Number):void {
            filter_.blurX = filter_.blurY = value;
        }
     
        public function set quality(value:int):void {
            filter_.quality = value;
        }

        private var filter_:BlurFilter;        
        private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;
        
        public function Smooth() {
            filter_ = new BlurFilter(2, 2, BitmapFilterQuality.MEDIUM);
        }
        
        public function applyEffect(value:BitmapData):BitmapData {
            value.applyFilter(value, value.rect, ZERO_POINT, filter_);
            return value;
        }
    }
    import flash.display.BitmapData;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.Point;
    
    class GrayScale implements IEffector {
       //RGB COLOURS
        private const R:Number = .8;//
        private const G:Number = .1;//
        private const B:Number = .8;//

        private const MATRIX:Array = [
            R, G, B, 0, 0,
            R, G, B, 0, 0,
            R, G, B, 0, 0,
            0, 0, 0, 1, 0
        ];
        private const FILTER:ColorMatrixFilter = new ColorMatrixFilter(MATRIX);
        
        private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;

        public function applyEffect(value:BitmapData):BitmapData {
            value.applyFilter(value, value.rect, ZERO_POINT, FILTER);
            return value;
        }
    }

    import flash.display.BitmapData;
    import flash.filters.ConvolutionFilter;
    import flash.geom.Point;
    
    class Negative implements IEffector {

        private const FILTER:ConvolutionFilter = new ConvolutionFilter(1, 1, [ -1], 1, 255);
        private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;
        
        public function applyEffect(value:BitmapData):BitmapData {
            value.applyFilter(value, value.rect, ZERO_POINT, FILTER);
            return value;
        }
    }

    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;
 
    class Binarize implements IEffector {
   
        public function get threshold():int { return _threshold; }
        public function set threshold(value:int):void {
            if (value < 0)   value = 0;
            if (value > 255) value = 255;
            _threshold = value;
        }
        private var _threshold:int = 127;    //:0 ~ 255
      
        public function get auto():Boolean { return _auto; }
        public function set auto(value:Boolean):void { _auto = value; }
        private var _auto:Boolean = false;

        private const ZERO_POINT:Point = EffectorUtils.ZERO_POINT;

        public function applyEffect(value:BitmapData):BitmapData {
            var bufferBmd:BitmapData = new BitmapData(value.width, value.height);
            var rect:Rectangle = bufferBmd.rect;
            bufferBmd = value.clone();

            if (_auto) {
                var hist:Vector.<Vector.<Number>> = value.histogram();
                var numOfPixel:uint = rect.width * rect.height;
                _threshold = calcThresholdRough(hist[2], numOfPixel);
            }
            
            value.fillRect(rect, 0x3299CC);
            value.threshold(bufferBmd, rect, ZERO_POINT, ">", _threshold, 0xFFFFFFFF, 0x000000FF, false);
            return value;
        }

        private function calcThresholdRough(hist:Vector.<Number>, numOfPixel:uint):uint {
            var total:uint;
            for (var i:int = 0; i < 256; i++) {
                total += hist[i] * i;
            }
            return total / numOfPixel >> 0;
        }
        
        private function calcThresholdStrict(hist:Vector.<Number>, numOfPixel:uint):uint {
            var maxSeparability:Number  = 0;  
            var maxDegree:uint = 0;               
            for (var i:int = 1; i < 255; i++) {
               //create var for below fucntion (calcSeparability)
                var Separability:Number = calcSeparability(i, hist, numOfPixel);
                if (Separability > maxSeparability) {
                    maxSeparability = Separability;
                    maxDegree       = i;
                }
            }
            return maxDegree;
        }
        
        //makes sure constant (a threshold for max and min number to never leave blank amount)
        private function calcSeparability(threshold:uint, hist:Vector.<Number>, numOfPixel:uint):Number {
            var i:uint;                                
            var num1:uint = 0, num2:uint = 0;        
            var con1:Number = 0, con2:Number = 0;   
            var con:Number = 0;                        
            var dis1:Number, dis2:Number;            
            var within:Number = 0;                    
            var between:Number = 0;                    
  
            for (i = 0; i < threshold; i++) {
                num1 += hist[i];
                con1 += i * hist[i];
            }
            for (i = threshold; i < 256; i++) {
                num2 += hist[i];
                con2 += i * hist[i];
            }
            con = (con1 + con2) / numOfPixel;    
            con1 /= num1;    
            con2 /= num2;    

            if (num1 == 0 || num2 == 0) return 0;
            
            for (i = 0; i < threshold; i++) {
                dis1 = i - con1;
                within += dis1 * dis1 * hist[i];
            }
            for (i = threshold; i < 256; i++) {
                dis2 = i - con2;
                within += dis2 * dis2 * hist[i];
            }
            within /= numOfPixel;

            for (i = 0; i < threshold; i++) {
                dis1 = con - con1;
                between += dis1 * dis1 * hist[i];
            }
            for (i = threshold; i < 256; i++) {
                dis2 = con - con2;
                between += dis2 * dis2 * hist[i];
            }
            between /= numOfPixel;
            
            return between / within;
        }
    }