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

PsychedelicCam

@author fumix
Get Adobe Flash player
by fumix 26 Jul 2010

    Talk

    fumix at 24 Jul 2010 02:09
    画面クリックでエフェクト?の切り替え
    fumix at 24 Jul 2010 02:12
    すごい重いのでEnterFrame内でエフェクトかけるのは止めた方が良かったかもしれない・・・
    fumix at 25 Jul 2010 11:26
    EnterFrameでエフェクトかけるのやめて、クリックでエフェクトかかった静止画を出すように変更。
    fumix at 26 Jul 2010 10:17
    ノイズ除去処理を追加した。

    Tags

    Embed
/**
 * Copyright fumix ( http://wonderfl.net/user/fumix )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/12Rl
 */

package {
    import net.hires.debug.Stats;

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.ConvolutionFilter;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.text.TextField;

    /**
     * @author fumix
     */
    [SWF(backgroundColor="#000000", frameRate="31", width="465", height="465")]

    public class PsychedelicCam extends Sprite {
        private var _w : int;
        private var _h : int;
        private var _camera : Camera;
        private var _video : Video;
        private var _bm : Bitmap;
        private var _bmd : BitmapData;
        private var _psycheFlag : Boolean;

        public function PsychedelicCam() {
            if(stage) initialize();
            else addEventListener(Event.ADDED_TO_STAGE, initialize);
        }

        /**
         * 初期化
         * @param event
         */
        private function initialize(event : Event = null) : void {
            removeEventListener(Event.ADDED_TO_STAGE, initialize);
            //背景設定
            _w = stage.stageWidth;
            _h = stage.stageHeight;
            var bmd : BitmapData = new BitmapData(_w, _h, true, 0x000000);
            addChild(new Bitmap(bmd));

            //webカメラ
            _camera = Camera.getCamera();
            _camera.setMode(_w, _h, 15);
            _video = new Video(_w, _h);
            _video.attachCamera(_camera);
            addChild(_video);            
            //カメラあり
            if(_camera != null) {
            
            //カメラ無し
            } else {
                var txt : TextField = new TextField();
                txt.textColor = 0xFFFFFF;
                txt.text = 'カメラ無し';
                addChild(txt);
            }
            
            //フラグ初期化
            _psycheFlag = false;
            
            //サイケ画像表示用
            _bm = new Bitmap();
            _bmd = new BitmapData(_w, _h, true, 0xFFFFFFFF);
            _bm.bitmapData = new BitmapData(_w, _h, true, 0xFF000000);
            _bm.visible = false;
            addChild(_bm);
            //Stats
            addChild(new Stats());
            
            Wonderfl.capture_delay( 20 );

            stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        }
        /**
         * マウスクリック
         * @param event
         */
        private function onMouseUp(event : MouseEvent) : void {
            _psycheFlag = !_psycheFlag;
            if(_psycheFlag) {
                _bm.visible = true;
                effect();
                //stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            }else{
                _bm.visible = false;
                //stage.removeEventListener(Event.ENTER_FRAME, onEnterFrame);                                
            }
        }
        /**
         * フレーム処理
         * @param event
         */
        private function onEnterFrame(event : Event) : void {
            effect();
        }

        /**
         * エフェクト処理
         */
        private function effect() : void {
            var colorArray : Array = [0xFF33CC33,0xFF3364FE,0xFFC727F9,0xFFFF4342,0xFFFFFF02,0xFF658448,0xFFFE33A8];
            colorArray = shuffleArray(colorArray);
            var bmd : BitmapData = new BitmapData(_w, _h);
            var thres : BitmapData;
            var edge : BitmapData;
            var min : int = 20;
            var max : int = 190;
            var step : int = 7;

            //ベースのbitmapをリセット
            _bm.bitmapData.copyPixels(_bmd, _bmd.rect, new Point(0, 0));
            //webカメラの画像を取得
            bmd.draw(_video);
            //グレースケール化
            var t:Number
            var g : BitmapData = grayscaleFilter(bmd);
            //ノイズ除去
            g = medianSmoothFilter(g);
            for (var i : int = 0;i <step;i ++) {
                t= min+(max-min)/step * i;
                //2値化    
                thres = thresholdFilter(g, t, colorArray[i]);                

                //2値化    
                edge = thresholdFilter(g, t);
                //エッジ検出
                edge = laplacianFilter(edge);
                //描画
                _bm.bitmapData.draw(thres, null, null, BlendMode.NORMAL);
                _bm.bitmapData.draw(edge, null, null, BlendMode.SUBTRACT);
            }
            //ビットマップ破棄
            bmd.dispose();
            thres.dispose();
            edge.dispose();
        }

        
        /**
         * 2値化処理
         * @param image
         * @param threshold
         * @param color
         * @return BitmapData
         */
        private function thresholdFilter(image : BitmapData,threshold : int,color : uint = 0xFFFFFFFF) : BitmapData {
            var d:BitmapData = new BitmapData(image.width, image.height);
            var r:Rectangle = new Rectangle(0, 0, image.width, image.height);
            d.fillRect(r, 0x00000000); // 不透明黒で塗りつぶす
            // 閾値以下を不透明黒にする
            d.threshold(image, r, new Point(0, 0), ">", threshold, color, 0x000000FF, false);
            return d;
        }
        /**
         * ノイズ除去
         * @param image
         * @return BitmapData
         */
        private function medianSmoothFilter(image : BitmapData) : BitmapData {
            var d:BitmapData = new BitmapData(image.width, image.height);
            var a:Array = new Array(9);
            for (var x:int = 0; x < image.width; x++) {
                for (var y:int = 0; y < image.height; y++) {
                    a[0] = image.getPixel(x - 1, y - 1) & 255;
                    a[1] = image.getPixel(x - 1, y) & 255;
                    a[2] = image.getPixel(x - 1, y + 1) & 255;
                    a[3] = image.getPixel(x, y - 1) & 255;
                    a[4] = image.getPixel(x, y) & 255;
                    a[5] = image.getPixel(x, y + 1) & 255;
                    a[6] = image.getPixel(x + 1, y - 1) & 255;
                    a[7] = image.getPixel(x + 1, y) & 255;
                    a[8] = image.getPixel(x + 1, y + 1) & 255;
                    a.sort(Array.NUMERIC); // ソートして
                    var c:int = a[4]; // 真ん中を取る
                    d.setPixel(x, y, (c << 16) | (c << 8) | c); // 中央値による色の設定
                }
            }
            return d;
       }
        /**
         * ラプラシアンフィルタ(エッジ処理)
         * @param image
         * @return BitmapData
         */
        private function laplacianFilter(image : BitmapData) : BitmapData {
            var d:BitmapData = new BitmapData(image.width, image.height);
            var rect : Rectangle = new Rectangle(0, 0, image.width, image.height);
            var p : Point = new Point(0, 0);
            var l:Array = [-1, -1, -1,
                           -1, +8, -1,
                           -1, -1, -1]; // ラプラシアンフィルタ
            d.applyFilter(image, rect, p,
                          new ConvolutionFilter(3, 3, l));
            return d;
        }

        /**
         * グレースケールフィルタ
         * @param imageData
         * @return BitmapData
         * @return BitmapData
         */
        private function grayscaleFilter(image : BitmapData) : BitmapData {
            var d : BitmapData = new BitmapData(image.width, image.height);
            var rect : Rectangle = new Rectangle(0, 0, image.width, image.height);
            var p : Point = new Point(0, 0);
            var cmatrix:ColorMatrixFilter = new ColorMatrixFilter([
                    1/3,1/3,1/3,0  ,0,                
                    1/3,1/3,1/3,0  ,0,                
                    1/3,1/3,1/3,0  ,0,
                    0  ,0  ,0  ,255,0]);
            
            d.applyFilter(image, rect, p, cmatrix);
            return d;
        }
        /**
         * 配列のシャッフル
         * @param arr
         * @return Array
         */
        private function shuffleArray(arr:Array):Array {
            var _len:uint = arr.length;
            var _reArr:Array = arr;
            
            while (_len) {
                
                var _m:uint = Math.floor(Math.random() * _len);
                var _n:uint = _reArr[--_len];
                _reArr[_len] = _reArr[_m];
                _reArr[_m] = _n ;
                
            }
            
            return _reArr;
        }    
    }
}