package {
    import flash.events.*;
    import flash.display.*;
    import flash.filters.*;
    import flash.geom.*;

    [SWF(width="360", height="320", backgroundColor="#ffffff", frameRate="5")]

    public class BackGroundDiff extends CameraFramework
    {
        public static const
            VIDEO_WIDTH:int = 320,          ///< ビデオの幅
            VIDEO_HEIGHT:int = 240,         ///< ビデオの高さ
            SCREEN_WIDTH:int = 360,         ///< 画面の幅
            SCREEN_HEIGHT:int = 320;        ///< 画面の高さ

        private static const
            DRAW_COMP:int = 0,
            DRAW_BACKGROUND:int = 1;

        private var backGround:BitmapData = null;
        private var drawState:int = DRAW_COMP;

        /// コンストラクタ
        public function BackGroundDiff()
        {
            super( SCREEN_WIDTH, SCREEN_HEIGHT, VIDEO_WIDTH, VIDEO_HEIGHT );
            drawBgColor(0xBB0054);

            /// 表示文字設定
            label.text = "背景画像を撮影してください";

            // ボタン追加
            var buttonY:int = 10, buttonW:int = 70;
            var compButton:TextButton = new TextButton(buttonW, 20, "背景差分");
            compButton.x = 10;
            compButton.y = buttonY;
            addChild(compButton);
            compButton.addEventListener( MouseEvent.CLICK, compButtonClick );

            var backButton:TextButton = new TextButton(buttonW, 20, "背景画像");
            backButton.x = compButton.x + compButton.width + 10;
            backButton.y = buttonY;
            addChild(backButton);
            backButton.addEventListener( MouseEvent.CLICK, backButtonClick );

            var backShotButton:TextButton = new TextButton(170, 20, "背景画像撮影");
            backShotButton.x = SCREEN_WIDTH - backShotButton.width - 2;
            backShotButton.y = SCREEN_HEIGHT - backShotButton.height - 10;
            addChild(backShotButton);
            backShotButton.addEventListener( MouseEvent.CLICK, backShotButtonClick );

        }

        private function compButtonClick(event:MouseEvent):void {
            drawState = DRAW_COMP;
        }

        private function backButtonClick(event:MouseEvent):void {
            drawState = DRAW_BACKGROUND;
        }

        private function backShotButtonClick(event:MouseEvent):void {

            if( video == null ){
                return;
            }

            if( backGround == null ){
                // こういうnullチェックってAS3でいるのかな?
                backGround = new BitmapData(VIDEO_WIDTH, VIDEO_HEIGHT, false, 0xffffff);
            }

            backGround.draw(video);

            // グレースケール化
            convertGrayScale(backGround);

            label.text = "背景差分の計算";
        }

        /// bitmapDataをグレースケール化する
        private function convertGrayScale( bmpData:BitmapData ):void {
            var cmf:ColorMatrixFilter = new ColorMatrixFilter(
                    [0.299, 0.587, 0.114, 0, 0,
                     0.299, 0.587, 0.114, 0, 0,
                     0.299, 0.587, 0.114, 0, 0]);
            bmpData.applyFilter(bmpData, bmpData.rect, new Point(), cmf);
        }

        /// RGBに変換
        private function getRGB(r:int, g:int, b:int):uint{
            return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
        }

        /// 描画処理
        public override function draw():void {

            if( backGround == null ){
                bd.draw(bdTmp);
                return;
            }

            // カメラの画像をグレースケール化       
            var grayBitmap:BitmapData = bdTmp.clone();
            convertGrayScale(grayBitmap);

            // 背景画像との差分をとる
            var compObj:Object = grayBitmap.compare(backGround);
            var compBitmap:BitmapData = null;

            if( compObj == 0 ){
                compBitmap = new BitmapData(bdTmp.width, bdTmp.height, true, 0x00000000);
            }else{
                compBitmap = BitmapData(compObj);
            }

            var BG_COLOR:uint = 0xFFFF0000;     ///< 背景部分の色
            var FT_COLOR:uint = 0x00000000;     ///< 前景部分の色

            // フォーカスが変わるせいか色見が微妙に変化するので、少ない差ならなくしちゃえ。差が少ないところは背景画像として塗りつぶし
            compBitmap.threshold(compBitmap, compBitmap.rect, new Point(), "<", 0x111111, BG_COLOR, 0x00ffffff);
            // 差がないところ(背景画像)は塗りつぶし。compareすると同じ色のところは0x00000000になる
            compBitmap.threshold(compBitmap, compBitmap.rect, new Point(), "==", 0x00000000, BG_COLOR);
            // 背景画像以外のところは、前景として塗りつぶし
            compBitmap.threshold(compBitmap, compBitmap.rect, new Point(), "!=", BG_COLOR, FT_COLOR);

            // 画面に描画
            bd.fillRect(bd.rect, 0x000000);

            switch(drawState){
            case DRAW_COMP:
                bd.draw(compBitmap);
                break;
            case DRAW_BACKGROUND:
                bd.draw(backGround);
                break;
            }

        }

    }
}