package {
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.filters.BitmapFilterQuality;
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.ui.Keyboard;
    
    [SWF(width=640, height=480, backgroundColor=0x0, frameRate=30)]

    public class ThresholdingMethods extends Sprite {
        
        private static const ZERO_POINT:Point = new Point();
        private static const IMG_RECT:Rectangle = new Rectangle(0, 0, 320, 240);
        
        private static const MONO_FILTER:ColorMatrixFilter = new ColorMatrixFilter([
            0.212671, 0.715160, 0.072169, 0, 0,
            0.212671, 0.715160, 0.072169, 0, 0,
            0.212671, 0.715160, 0.072169, 0, 0,
            0, 0, 0, 1, 0
        ]);
        private static const BLUR_FILTER8:BlurFilter = new BlurFilter(8, 8, BitmapFilterQuality.LOW);
        private static const BLUR_FILTER16:BlurFilter = new BlurFilter(16, 16, BitmapFilterQuality.LOW);

        private var _camera:Camera;
        private var _video:Video;
        private var _color:ColorTransform;

        private var _bmp1:BitmapData;
        private var _bmp2:BitmapData;
        private var _bmp3:BitmapData;
        private var _bmp4:BitmapData;
        private var _bmp5:BitmapData;
        private var _bmp6:BitmapData;
        private var _bmp7:BitmapData;
        private var _bmp8:BitmapData;
        
        public function ThresholdingMethods() {
            this._camera = Camera.getCamera();
            this._camera.setMode(320, 240, 30);
            this._video = new Video(320, 240);
            this._video.attachCamera(this._camera);
            this._color = new ColorTransform(1, 1, 1, 1, 0, 0, 0, 0);
            
            var b:Bitmap;
            this._bmp1 = new BitmapData(320, 240, false, 0x0);
            b = this.addChild(new Bitmap(this._bmp1)) as Bitmap;
            b.x = 160
            
            this._bmp2 = this._bmp1.clone();
            
            this._bmp3 = this._bmp1.clone();
            b = this.addChild(new Bitmap(this._bmp3)) as Bitmap;
            b.y = 240;
            
            this._bmp4 = this._bmp1.clone();
            this._bmp5 = this._bmp1.clone();
            this._bmp6 = this._bmp1.clone();
            this._bmp7 = this._bmp1.clone();
            b = this.addChild(new Bitmap(this._bmp7)) as Bitmap;
            b.x = 320;
            b.y = 240;

            this.addEventListener(Event.ENTER_FRAME, this._update);
            this.stage.addEventListener(KeyboardEvent.KEY_DOWN, this._onKeyDown);
        }
        
        private function _update(e:Event):void {
            // source
            this._bmp1.draw(this._video, null, this._color);
            
            // mono
            this._bmp2.applyFilter(this._bmp1, IMG_RECT, ZERO_POINT, MONO_FILTER);
            
            // global constant thresholding
            this._bmp3.fillRect(IMG_RECT, 0x0);
            this._bmp3.threshold(this._bmp2, IMG_RECT, ZERO_POINT, '>', 128, 0xffffffff, 0xff);

            // local adaptive thresholding (16 pix blur)
            this._bmp4.applyFilter(this._bmp2, IMG_RECT, ZERO_POINT, BLUR_FILTER16);
            this._bmp5.copyPixels(this._bmp2, IMG_RECT, ZERO_POINT);
            this._bmp5.draw(this._bmp4, null, null, BlendMode.SUBTRACT);
            this._bmp7.fillRect(IMG_RECT, 0x0);
            this._bmp7.threshold(this._bmp5, IMG_RECT, ZERO_POINT, '>', 0, 0xffffffff, 0xff);
        }

        private function _onKeyDown(e:KeyboardEvent):void {
            switch (e.keyCode) {
                case Keyboard.UP:
                    this._color.redOffset += 8;
                    this._color.greenOffset += 8;
                    this._color.blueOffset += 8;
                    break;
                case Keyboard.DOWN:
                    this._color.redOffset -= 8;
                    this._color.greenOffset -= 8;
                    this._color.blueOffset -= 8;
                    break;
                case Keyboard.RIGHT:
                    this._color.redMultiplier += 0.1;
                    this._color.greenMultiplier += 0.1;
                    this._color.blueMultiplier += 0.1;
                    break;
                case Keyboard.LEFT:
                    this._color.redMultiplier -= 0.1;
                    this._color.greenMultiplier -= 0.1;
                    this._color.blueMultiplier -= 0.1;
                    break;
            }
        }
    }
}