flash on 2013-11-24

by Mihail.Podivilov
LOGOSWARE Class Library.

Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA

QRコード解析クラスの使用例です
@author Kenichi UENO
♥0 | Line 1864 | Modified 2013-11-24 00:06:33 | MIT License
play

ActionScript3 source code

/**
 * Copyright Mihail.Podivilov ( http://wonderfl.net/user/Mihail.Podivilov )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tcXn
 */

package 
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.GradientType;
    import flash.display.SimpleButton;
    import flash.display.SpreadMethod;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.events.TimerEvent;
    import flash.filters.BlurFilter;
    import flash.filters.DropShadowFilter;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.media.Camera;
    import flash.media.Video;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    import flash.text.TextFormat;
    import flash.utils.Timer;
    public class ReadQrCodeSample extends Sprite 
    {
        private const SRC_SIZE:int = 320;
        private const STAGE_SIZE:int = 350;
        
        private var getQRimage:GetQRimage;
        private var qrDecode:QRdecode = new QRdecode();

        private var errorView:Sprite;
        private var errorText:TextField = new TextField();
        
        private var startView:Sprite;
        
        private var cameraView:Sprite;
        private var camera:Camera;
        private var video:Video = new Video(SRC_SIZE, SRC_SIZE);
        private var freezeImage:Bitmap;
        private var blue:Sprite = new Sprite();
        private var red:Sprite = new Sprite();
        private var blurFilter:BlurFilter = new BlurFilter();
        
        private var resultView:Sprite;
        private var textArea:TextField = new TextField();
        private var cameraTimer:Timer = new Timer(2000);
        
        private var textArray:Array = ["", "", ""];
        /**
         * コンストラクタ
         */
        public function ReadQrCodeSample():void {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            errorView = buildErrorView();
            
            cameraTimer.addEventListener(TimerEvent.TIMER, getCamera);
            cameraTimer.start();
            getCamera();
        }
        /**
         * カメラの接続をチェックします
         */
        private function getCamera(e:TimerEvent = null):void{
            camera = Camera.getCamera();
            this.graphics.clear();
            if ( camera == null ) {
                this.addChild( errorView );
            } else {
                cameraTimer.stop();
                if ( errorView.parent == this ) {
                    this.removeChild(errorView);
                }
                start();
            }
        }
        /**
         * スタートボタンを表示
         */
        private function start():void {
            startView = buildStartView();
            
            this.addChild( startView );
            
            startView.addEventListener(MouseEvent.CLICK, onStart);
        }
        /**
         * 画像解析クラスにカメラ画像を渡し、解析完了イベントを監視します
         */
        private function onStart(e:MouseEvent):void {
            cameraView = buildCameraView();
            resultView = buildResultView();
            
            this.addChild( cameraView );
            this.addChild( resultView );
            this.removeChild( startView );
            resultView.visible = false;
            
            getQRimage = new GetQRimage(video);
            getQRimage.addEventListener(QRreaderEvent.QR_IMAGE_READ_COMPLETE, onQrImageReadComplete);
            qrDecode.addEventListener(QRdecoderEvent.QR_DECODE_COMPLETE, onQrDecodeComplete);
            redTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onRedTimer );
            this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        /**
         * エラー画面を作成
         */
        private function buildErrorView():Sprite {
            var sprite:Sprite = new Sprite();
            errorText.autoSize = TextFieldAutoSize.LEFT;
            errorText.text = "no camera detected.";
            errorText.x = 0.5 * (STAGE_SIZE - errorText.width);
            errorText.y = 0.5 * (STAGE_SIZE - errorText.height);
            errorText.border = true;
            errorText.background = true;
            sprite.graphics.lineStyle(0);
            sprite.graphics.drawPath(Vector.<int>([1, 2, 2, 2, 2, 2, 1, 2]), Vector.<Number>([5, 5, STAGE_SIZE-5, 5, STAGE_SIZE-5, STAGE_SIZE-5, 5, STAGE_SIZE-5, 5, 5, STAGE_SIZE-5, STAGE_SIZE-5, 5, STAGE_SIZE-5, STAGE_SIZE-5, 5]));
            sprite.addChild(errorText);
            return sprite;
        }
        /**
         * 開始ボタンを作成
         */
        private function buildStartView():Sprite {
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginGradientFill(GradientType.LINEAR, [0xCCCCCC, 0xAAAAAA], [1.0, 1.0], [0, 255], new Matrix(0, 0.03, -0.03, 0, 0, 15));
            sprite.graphics.lineStyle(2);
            sprite.graphics.drawRoundRect(0, 0, 200, 30, 5);
            
            var btnText:TextField = new TextField();
            btnText.autoSize = TextFieldAutoSize.LEFT;
            btnText.text = "Cane Code Reader";
            btnText.setTextFormat(new TextFormat(null, 16, null, true));
            btnText.selectable = false;
            
            btnText.x = 0.5 * (sprite.width - btnText.width);
            btnText.y = 0.5 * (sprite.height - btnText.height);
            
            sprite.addChild(btnText);
            sprite.mouseChildren = false;
            sprite.buttonMode = true;
            
            sprite.x = 0.5 * (STAGE_SIZE - sprite.width);
            sprite.y = 0.5 * (STAGE_SIZE - sprite.height);
            
            return sprite;
        }
        /**
         * カメラの表示部分を作成
         */
        private function buildCameraView():Sprite {
            camera.setQuality(0, 100);
            camera.setMode(SRC_SIZE, SRC_SIZE, 24, true );
            video.attachCamera( camera );
            
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginGradientFill(GradientType.LINEAR, [0xCCCCCC, 0x999999], [1.0, 1.0], [0, 255], new Matrix(0, 0.1, -0.1, 0, 0, 150));
            sprite.graphics.drawRoundRect(0, 0, SRC_SIZE+30, SRC_SIZE+30, 20);
            
            var videoHolder:Sprite = new Sprite();
            videoHolder.addChild( video );
            videoHolder.x = videoHolder.y = 15;
            
            freezeImage = new Bitmap(new BitmapData(SRC_SIZE, SRC_SIZE));
            videoHolder.addChild( freezeImage );
            freezeImage.visible = false;
            
            red.graphics.lineStyle(2, 0xFF0000);
            red.graphics.drawPath(Vector.<int>([1,2,2,1,2,2,1,2,2,1,2,2]), Vector.<Number>([30,60,30,30,60,30,290,60,290,30,260,30,30,260,30,290,60,290,290,260,290,290,260,290]));
            blue.graphics.lineStyle(2, 0x0000FF);
            blue.graphics.drawPath(Vector.<int>([1,2,2,1,2,2,1,2,2,1,2,2]), Vector.<Number>([30,60,30,30,60,30,290,60,290,30,260,30,30,260,30,290,60,290,290,260,290,290,260,290]));

            sprite.addChild( videoHolder );
            sprite.addChild( red );
            sprite.addChild( blue );
            blue.alpha = 0;
            red.x = red.y = 15;
            blue.x = blue.y = 15;
            return sprite;
        }
        /**
         * 結果表示用Sprite作成
         */
        private function buildResultView():Sprite {
            var sprite:Sprite = new Sprite();
            sprite.graphics.beginGradientFill(GradientType.LINEAR, [0xDDDDEE, 0xBBBBCC], [0.9, 0.9], [0, 255], new Matrix(0, 0.1, -0.1, 0, 0, 150));
            sprite.graphics.drawRoundRect(0, 0, 280, 280, 20);
            
            sprite.addChild( textArea );
            textArea.width = 250;
            textArea.height = 200;
            textArea.wordWrap = true;
            textArea.multiline = true;
            textArea.border = true;
            textArea.background = true;
            textArea.backgroundColor = 0xFFFFFF;
            textArea.x = textArea.y = 15;
            
            var btnText:TextField = new TextField();
            btnText.autoSize = TextFieldAutoSize.LEFT;
            btnText.text = "CLOSE";
            btnText.selectable = false;
            var btnSprite:Sprite = new Sprite();
            btnSprite.addChild(btnText);
            btnSprite.graphics.lineStyle(1);
            btnSprite.graphics.beginGradientFill(GradientType.LINEAR, [0xEEEEEE, 0xCCCCCC], [0.9, 0.9], [0, 255], new Matrix(0, 0.01, -0.01, 0, 0, 10));
            btnSprite.graphics.drawRoundRect(0, 0, 80, 20, 8);
            btnText.x = 0.5 * (btnSprite.width - btnText.width);
            btnText.y = 0.5 * (btnSprite.height - btnText.height);
            btnSprite.x = 0.5 * ( 280 - 80 );
            btnSprite.y = 240;
            btnSprite.buttonMode = true;
            btnSprite.mouseChildren = false;
            btnSprite.addEventListener(MouseEvent.CLICK, onClose);
            
            sprite.addChild( btnSprite );
            sprite.addChild( textArea );
            
            sprite.x = sprite.y = 35;
            sprite.filters = [new DropShadowFilter(4.0,45,0,0.875)];
            
            return sprite;
        }
        /**
         * 解析を毎フレーム行う
         */
        private function onEnterFrame(e: Event):void{
            if( camera.currentFPS > 0 ){
                getQRimage.process();
            }
        }
        /**
         * QRコードを発見したらデコーダーに渡す
         */
        private function onQrImageReadComplete(e: QRreaderEvent):void{
            qrDecode.setQR(e.data); // QRreaderEvent.data: QRコード配列
            qrDecode.startDecode(); // デコード開始
        }
        /**
         * デコードが完了したら結果テキストを表示する
         */
        private function onQrDecodeComplete(e: QRdecoderEvent):void {
            blue.alpha = 1.0;
            redTimer.reset();
            redTimer.start();
            textArray.shift();
            textArray.push( e.data );  // QRdecoderEvent.data: 解析文字列
            if ( textArray[0] == textArray[1] && textArray[1] == textArray[2] ) {
                textArea.htmlText = e.data;
                cameraView.filters = [blurFilter];
                redTimer.stop();
                freezeImage.bitmapData.draw(video);
                freezeImage.visible = true;
                this.removeEventListener(Event.ENTER_FRAME, onEnterFrame);
                resultView.visible = true;
            }
        }
        /**
         * 結果を削除
         */
        private function onClose(e: MouseEvent):void {
            textArray = ["", "", ""];
            freezeImage.visible = false;
            redTimer.start();
            this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
            cameraView.filters = [];
            resultView.visible = false;
        }
        private var redTimer:Timer = new Timer(400, 1);
        /**
         * ガイドの色を戻す
         */
        private function onRedTimer(e:TimerEvent):void {
            blue.alpha = 0;
        }
    }
    
}

//足りない定義をコピペした
// > svn co http://www.libspark.org/svn/as3/QRCodeReader/trunk/src/com/logosware/
// > cd logosware
// > ruby -ape "$_.gsub!(/^package.*$/, '/* \\0 */') or $_.gsub!(/^(\s*)public class/, '\\1/* public */ internal class') or $_.gsub!(/^(\s*)(import com.logosware.*)$/, '\\1/* \\2 */')" event\*.as utils\*.as utils\QRcode\*.as > hoge.txt

/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.event */
{
    import flash.events.Event;
    
    /**
     * QRコードのデコード完了イベントを送出します
     */
    /* public */ internal class QRdecoderEvent extends Event
    {
        // 定数( Class constants )
        
        /**
         * デコード完了を通知します。
         * @eventType QR_DECODE_COMPLETE
         **/
        public static const QR_DECODE_COMPLETE:String = "QR_DECODE_COMPLETE";
        
        // プロパティ( Proerties )
        
        /**
         * 解析した結果の文字列が格納されます
         **/
        public var data:String;
        /**
         * 解析に用いたコード配列が格納されます
         **/
        public var checkArray:Array;
        
        // コンストラクタ( Constructor )
        
        /**
         * コンストラクタ
         * @param type イベントタイプ
         * @param data 抽出文字列
         * @param check 入力したコード
         **/
        public function QRdecoderEvent(type:String, data:String, check:Array){
            super(type);
            // 新しいプロパティを設定する
           this.data = data;
           this.checkArray = check;
        }
        // Eventからオーバーライドしたメソッド( Overridden Method: Event )
        /**
        * @private
        **/
        override public function clone():Event {
            return new QRdecoderEvent(type, data, checkArray);
        }
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.event */
{
    import flash.display.BitmapData;
    import flash.events.Event;
    
    /**
     * QRコード画像の抽出完了イベントを送出します
     */
    /* public */ internal class QRreaderEvent extends Event
    {
        // 定数( Class constants )
        
        /**
         * QRコードの抽出完了を通知します。
         * @eventType QR_IMAGE_READ_COMPLETE
         **/
        public static const QR_IMAGE_READ_COMPLETE:String = "QR_IMAGE_READ_COMPLETE";

        // プロパティ( Proerties )
        
        /**
         * 解析した結果のQRコード画像が格納されます
         **/
        public var imageData:BitmapData;
        /**
         * 解析した結果のQRコード画像のビットパターン配列が格納されます
         **/
        public var data:Array;
        /**
         * 入力した任意の配列が格納されます(デバッグ用)
         **/
        public var checkArray:Array;

        // コンストラクタ( Constructor )
        
        /**
         * コンストラクタ
         * @param type イベントタイプ
         * @param imageData 抽出したQRコード画像
         * @param data 抽出したQRコードのビット列
         * @param check 入力した任意のコード
         **/
        public function QRreaderEvent(type:String, imageData:BitmapData, data:Array, checkArray:Array = null){
            super(type);
            // 新しいプロパティを設定する
           this.imageData = imageData;
           this.data = data;
           this.checkArray = checkArray;
        }

        // Eventからオーバーライドしたメソッド( Overridden Method: Event )

        /**
        * @private
        **/
        override public function clone():Event {
            return new QRreaderEvent(type, imageData, data, checkArray);
        }
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils */
{
    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    /**
     * ラベリングを行うクラスです
     */
    /* public */ internal class LabelingClass
    {
        private var _bmp:BitmapData;
        private var _minSize:uint;
        private var _startColor:uint;
        private var _pickedRects:Array = [];
        private var _pickedColor:Array = [];
        /**
         * コンストラクタ
         * @param bmp 入力画像(0x0, 0xFFFFFFFFでニ値化されたもの)
         * @param minSize 画素として認める最低サイズ(ノイズ対策)
         * @param startColor 塗り開始色
         * @param isChangeOriginal 入力画像を実際に塗るかどうか 
         **/
        public function Labeling(bmp:BitmapData, minSize:uint = 10, startColor:uint = 0xFFFFFFFE, isChangeOriginal:Boolean = true):void{
            _minSize = minSize;
            _startColor = startColor;
            if( isChangeOriginal ){
                _bmp = bmp;
            } else {
                _bmp = bmp.clone();
            }
            _process();
        }
        /**
         * ラベリングした結果得られた範囲の矩形情報を返します
         * @return 矩形の配列
         **/
        public function getRects():Array{
            return _pickedRects;
        } 
        /**
         * ラベリングした結果得られた範囲を塗った色情報を返します
         * @return 色の配列
         **/
        public function getColors():Array{
            return _pickedColor;
        }
        /**
         * コア関数
         **/
        private function _process():void {
            var _fillColor:uint = _startColor;
            var _rect:Rectangle;
            while (_paintNextLabel( _bmp, 0xFF000000, _fillColor ) ){
                _rect = _bmp.getColorBoundsRect( 0xFFFFFFFF, _fillColor );
                if ( ( _rect.width > _minSize) && ( _rect.height > _minSize ) ) {
                    var _tempRect:Rectangle = _rect.clone();
                    _pickedRects.push( _tempRect );
                    _pickedColor.push( _fillColor );
                }
                _fillColor --;
            }
        }
        /**
         * 次のpickcolor色の領域をfillcolor色に塗る。pickcolorが見つからなければfalseを返す
         * @param bmp 画像
         * @param pickcolor 次の色
         * @param fillcolor 塗る色
         * @return 目的の色があったかどうか
         **/
        private function _paintNextLabel( bmp:BitmapData, pickcolor:uint, fillcolor:uint ):Boolean {
            var rect:Rectangle = bmp.getColorBoundsRect( 0xFFFFFFFF, pickcolor );
            if( (rect.width > 0) && (rect.height> 0) ){
                var tempBmp:BitmapData = new BitmapData( rect.width, 1 );
                tempBmp.copyPixels( bmp, new Rectangle(rect.topLeft.x, rect.topLeft.y, rect.width, 1 ), new Point(0, 0) );
                var rect2:Rectangle = tempBmp.getColorBoundsRect( 0xFFFFFFFF, pickcolor );
                bmp.floodFill( rect2.topLeft.x + rect.topLeft.x, rect2.topLeft.y + rect.topLeft.y, fillcolor );
                return true;
            }
            return false;
        }
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode */
{
    /* import com.logosware.utils.QRcode.GFstatic; */
    /**
     * GF(2^4)を扱うためのクラス
     **/
    /* public */ internal class G4Num {
        private var _vector:uint;
        private var _power:int;
        /**
         * コンストラクタ
         * @param power 指数
         **/
        public function G4Num(power:int) {
            setPower( power );
        }
        /**
         * 指数を指定する
         * @param power 指数
         **/
        public function setPower( power:int ):void {
            _power = power;
            if ( _power < 0 ) {
                _vector = 0;
            } else {
                _power %= 15;
                _vector = GFstatic._power2vector_4[_power];
            }
        }
        /**
         * 整数値を指定する
         * @param vector 整数値
         **/
        public function setVector( vector:uint ):void {
            _vector = vector;
            _power = GFstatic._vector2power_4[_vector];
        }
        /**
         * 整数値を取得する
         * @param 整数値
         **/
        public function getVector():uint {
            return _vector;
        }
        /**
         * 指数を取得する
         * @param 指数
         **/
        public function getPower():int {
            return _power;
        }
        /**
         * 足し算を行う。整数値同士のxorを取る。
         * @param other 足す対象となるG4Numインスタンス
         * @param 計算結果
         **/
        public function plus( other:G4Num ):G4Num {
            var newVector:uint = _vector ^ other.getVector();
            return new G4Num( GFstatic._vector2power_4[ newVector ] );
        }
        /**
         * 乗算を行う。指数同士の足し算を行う。
         * @param other かける対象となるG4Numインスタンス
         * @param 計算結果
         **/
        public function multiply( other:G4Num ):G4Num {
            if ( (_power == -1) || (other.getPower() == -1 ) ) {
                return new G4Num( -1 );
            } else {
                return new G4Num( _power + other.getPower() );
            }
        }
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode */
{
    /* import com.logosware.utils.QRcode.GFstatic; */
    /**
     * GF(2^8)を扱うためのクラス
     **/
    /* public */ internal class G8Num {
        private var _vector:uint;
        private var _power:int;
        /**
         * コンストラクタ
         * @param power 指数
         **/
        public function G8Num(power:int) {
            setPower( power );
        }
        /**
         * 指数を指定する
         * @param power 指数
         **/
        public function setPower( power:int ):void {
            _power = power;
            if ( _power < 0 ) {
                _vector = 0;
            } else {
                _power %= 255;
                _vector = GFstatic._power2vector_8[_power];
            }
        }
        /**
         * 整数値を指定する
         * @param vector 整数値
         **/
        public function setVector( vector:uint ):void {
            _vector = vector;
            _power = GFstatic._vector2power_8[_vector];
        }
        /**
         * 整数値を取得する
         * @param 整数値
         **/
        public function getVector():uint {
            return _vector;
        }
        /**
         * 指数を取得する
         * @param 指数
         **/
        public function getPower():int {
            return _power;
        }
        /**
         * 足し算を行う。整数値同士のxorを取る。
         * @param other 足す対象となるG4Numインスタンス
         * @param 計算結果
         **/
        public function plus( other:G8Num ):G8Num {
            var newVector:uint = _vector ^ other.getVector();
            return new G8Num( GFstatic._vector2power_8[ newVector ] );
        }
        /**
         * 乗算を行う。指数同士の足し算を行う。
         * @param other かける対象となるG4Numインスタンス
         * @param 計算結果
         **/
        public function multiply( other:G8Num ):G8Num {
            if ( (_power < 0) || (other.getPower() < 0 ) ) {
                return new G8Num( -1 );
            } else {
                return new G8Num( _power + other.getPower() );
            }
        }
        /**
         * 逆数を計算して得る。元のインスタンスは変化しない。
         * @param 計算結果
         **/
        public function inverse():G8Num {
            return new G8Num( 255 - getPower() );
        }
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode */
{
    /* import com.logosware.event.QRreaderEvent; */
    /* import com.logosware.utils.LabelingClass; */
    
    import flash.display.*;
    import flash.events.EventDispatcher;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.ConvolutionFilter;
    import flash.geom.*;
    import flash.utils.ByteArray;

    /**
     * 主にカメラ画像からQRコードを切り出すためのクラスです.
     * 画像上にあるVersion 1~10のQRコードを0,1からなる2次元配列に整形して返します
     * @author Kenichi UENO
     **/
    /* public */ internal class GetQRimage extends EventDispatcher
    {
        private var _wid:uint = 320;
        private var _hgt:uint = 240;
        private var _minVersion:uint = 1; // サポートする最低バージョン
        private var _maxVersion:uint = 10; // サポートする最高バージョン
        
        private var _imageSource:DisplayObject = new Sprite();
        private var _resultImage:BitmapData = new BitmapData(1, 1);
        private var _resultArray:Array = [];
        private var _results:Array = [
            _resultImage,
            _resultArray
        ];
        private const _origin:Point = new Point(0, 0);
        private var detecter:QRCodeDetecter;

        /**
         * コンストラクタ.
         * @param tempMC QRコード描画元のSpriteインスタンス
         **/
        public function GetQRimage(source:DisplayObject)
        {
            _imageSource = source;
            detecter = new QRCodeDetecter(_imageSource);
        }

        /**
         * 読み取りを実行します
         * @eventType QRreaderEvent.QR_IMAGE_READ_COMPLETE
         */
        public function process():void {
            var QRCodes:Array = detecter.detect();
            for ( var i:int = 0; i < QRCodes.length; i++ ) {
                var bmpData:BitmapData = QRCodes[i].image;
                var colors:Array = QRCodes[i].borderColors;
                // バージョンの取得
                var qrInfo:Object = _getVersion( bmpData, colors[0], colors[1], colors[2] );
                if ( qrInfo.version > 0 ) {
                    // グリッドの結果を取得
                    _results = _getGrid( bmpData, qrInfo );
                    _resultImage = _results[0];
                    _resultArray = _results[1];
                    
                    // グリッド中でもマーカー確認
                    var checkBmp:BitmapData = new BitmapData( _resultImage.width, _resultImage.height );
                    checkBmp.applyFilter(_resultImage,_resultImage.rect,_origin,new ConvolutionFilter(7, 7, [1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1],33));
                    if ( (checkBmp.getPixel(7, 7) == 0) && (checkBmp.getPixel(checkBmp.width - 8, 7) == 0) && (checkBmp.getPixel(7, checkBmp.height - 8) == 0) ) {
                        dispatchEvent( new QRreaderEvent( QRreaderEvent.QR_IMAGE_READ_COMPLETE, _resultImage, _resultArray ) );
                    } else {
                    }
                }
            }
            // process終了
        }
        /**
         * QRコードのビット情報を二次元配列化する
         * @param bmpData 画像
         * @param qrInfo QRコード情報オブジェクト
         * @param ビットパターン配列
         */
        private function _getGrid( bmpData:BitmapData, qrInfo:Object ):Array {
            var __resultBmp:BitmapData = new BitmapData( 8 + qrInfo.version * 4 + 17, 8 + qrInfo.version * 4 + 17 );
            var __resultArray:Array = new Array( qrInfo.version * 4 + 17 );
            var __i:uint;
            var __thisColor:uint;
            var __tlCenter:Object = { x:qrInfo.topLeftRect.topLeft.x + 0.5 * ( qrInfo.topLeftRect.width ), y:qrInfo.topLeftRect.topLeft.y + 0.5 * ( qrInfo.topLeftRect.height ) };
            var __trCenter:Object = { x:qrInfo.topRightRect.topLeft.x + 0.5 * ( qrInfo.topRightRect.width ), y:qrInfo.topRightRect.topLeft.y + 0.5 * ( qrInfo.topRightRect.height ) };
            var __blCenter:Object = { x:qrInfo.bottomLeftRect.topLeft.x + 0.5 * ( qrInfo.bottomLeftRect.width ), y:qrInfo.bottomLeftRect.topLeft.y + 0.5 * ( qrInfo.bottomLeftRect.height ) };
            for( __i = 0; __i < (qrInfo.version*4+17); __i++ ){
                __resultArray[__i] = new Array( qrInfo.version * 4 + 17 );
            }
            __i = 0;
            __thisColor = 0;
            while ( __thisColor != 0xFFFFFF ) {
                __i++;
                __thisColor = bmpData.getPixel( qrInfo.topRightRect.topLeft.x + __i, qrInfo.bottomLeftRect.topLeft.y + __i );
            }
            bmpData.floodFill( qrInfo.topRightRect.topLeft.x + __i, qrInfo.bottomLeftRect.topLeft.y + __i, 0xFFCCFFFF );
            
            var __bottomRightRect:Rectangle = bmpData.getColorBoundsRect( 0xFFFFFFFF, 0xFFCCFFFF );
            bmpData.floodFill( qrInfo.topRightRect.topLeft.x + __i, qrInfo.bottomLeftRect.topLeft.y + __i, 0xFFFFFFFF );
            var __brCenter:Object = { x:__bottomRightRect.topLeft.x + 0.5 * ( __bottomRightRect.width ), y:__bottomRightRect.topLeft.y + 0.5 * ( __bottomRightRect.height ) };
            
            if( qrInfo.version == 1 ){
                __brCenter.x = __blCenter.x + (__trCenter.x - __tlCenter.x) * 11.0 / 14.0;
                __brCenter.y = __trCenter.y + (__blCenter.y - __tlCenter.y) * 11.0 / 14.0;
            }
            
            var __tempNum1:Number = ( qrInfo.version * 4.0 + 17 - 10 ); //QRコード上の、左上マーカー中心から右「下」マーカー中心までのx座標の差 (ver5なら27)
            var __tempNum2:Number = ( qrInfo.version * 4.0 + 17 - 7 ); //QRコード上の、左上マーカー中心から右「上」マーカー中心までのx座標の差 (ver5なら30)
            
            var __blTop:Object = { x: qrInfo.bottomLeftRect.topLeft.x + qrInfo.bottomLeftRect.width*0.5, y: qrInfo.bottomLeftRect.topLeft.y + qrInfo.bottomLeftRect.height/14.0 };
            var __trLeft:Object = { x: qrInfo.topRightRect.topLeft.x + qrInfo.topRightRect.width / 14.0, y: qrInfo.topRightRect.topLeft.y + qrInfo.topRightRect.height * 0.5 };
            
            var __sum:Number = 0.0;
            var __num:Number = 0.0;
            
            for ( __i = __blTop.y - qrInfo.cellSize; __i <= __blTop.y + qrInfo.cellSize; __i++ ) {
                if ( bmpData.getPixel( __blTop.x, __i ) != 0xFFFFFF ) {
                    __sum += __i;
                    __num++;
                }
            }
            __blTop.y = 0.5 * (__blTop.y + __sum / __num);
            
            var __a3:Number = ( __tlCenter.y - __trLeft.y) / ( __tlCenter.x - __trLeft.x);
            var __a30:Number = ( __blTop.y - __brCenter.y) / ( __blTop.x - __brCenter.x);
            var __b3:Number = __trLeft.y - __a3 * __trLeft.x;
            var __b30:Number = __brCenter.y - __a30 * __brCenter.x;
            var __startX3:Number = __tlCenter.x + ( __trLeft.x - __tlCenter.x ) * ( -3.0 / __tempNum1 );
            var __startX30:Number = __blTop.x + ( __brCenter.x - __blTop.x ) * ( -3.0 / __tempNum1 );
            var __startY3:Number = __tlCenter.y + ( __trLeft.y - __tlCenter.y ) * ( -3.0 / __tempNum1 );
            var __startY30:Number = __blTop.y + ( __brCenter.y - __blTop.y ) * ( -3.0 / __tempNum1 );
            var __end3:Number = __trLeft.x + ( __trLeft.x - __tlCenter.x ) * ( 6.0 / __tempNum1 );
            var __end30:Number = __brCenter.x + ( __brCenter.x - __blTop.x ) * ( 6.0 / __tempNum1 );
            var __loopConst:uint = (__resultBmp.width - 8 );
            var __loopConst2:uint = __loopConst - 1;
            var __a:Array = new Array( __loopConst );
            var __b:Array = new Array( __loopConst );
            var __startX:Array = new Array( __loopConst );
            var __startY:Array = new Array( __loopConst );
            var __endX:Array = new Array( __loopConst );
            
            for ( __i = 0; __i < __loopConst; __i++ ) {
                __a[__i] =  (( __a30 - __a3 ) / __tempNum1) * ( __i - 3 ) + __a3;
                __startX[__i] = (( __startX30 - __startX3 ) / __tempNum1) * ( __i - 3 ) + __startX3;
                __startY[__i] = (( __startY30 - __startY3 ) / __tempNum1) * ( __i - 3 ) + __startY3;
                __endX[__i] = (( __end30 - __end3 ) / __tempNum1) * ( __i - 3 ) + __end3;
                __b[__i] =  __startY[__i] - __a[__i] * __startX[__i];
            }
            for ( var __y:Number = 0; __y < __loopConst; __y++ ) {
                var __y2:Number = __y - 3;
                for ( var __x:Number = 0; __x < __loopConst; __x++ ) {
                    var __x2:Number = __x - 3;
                    if ( (bmpData.getPixel( __startX[__y] + ( __endX[__y] - __startX[__y] ) * ( __x / __loopConst2 ), __a[__y] * (__startX[__y] + ( __endX[__y] - __startX[__y] ) * ( __x / __loopConst2 )) + __b[__y] ) & 0xFF0000) < 0xFF0000) {
                        __resultBmp.setPixel( 4 + __x, 4 + __y, 0 );
                        __resultArray[__y][__x] = 1;
                    }
                }
            }
            return [__resultBmp, __resultArray];
        }
        /**
         * QRコードのバージョンを判別する
         * @param bmp 画像
         * @param QRコード情報オブジェクト
         */
        private function _getVersion( bmp:BitmapData, tlColor:uint, trColor:uint, blColor:uint ):Object {
            var i:uint;
            var thisColor:uint;
            bmp.lock();
            var topLeftRect:Rectangle = bmp.getColorBoundsRect( 0xFFFFFFFF, tlColor );
            var topRightRect:Rectangle = bmp.getColorBoundsRect( 0xFFFFFFFF, trColor );
            var bottomLeftRect:Rectangle = bmp.getColorBoundsRect( 0xFFFFFFFF, blColor );
            var startTopLeft:Point = new Point( 26, topLeftRect.topLeft.y + topLeftRect.height );
            var numX:uint = 0;
            var tempX:uint;
            var oldP:uint;
            var whiteNum:uint = 0;
            for ( var j:int = -8; j <= 0; j++ ) {
                tempX = 0;
                var whiteArray:Array = [];
                var tempArray:ByteArray = bmp.getPixels( new Rectangle( startTopLeft.x, startTopLeft.y + j, bmp.width - 52, 1 ) );
                var startColor:uint = tempArray[1];
                var endColor:uint = tempArray[4*(bmp.width-26-1)+1];
                if ( ( startColor != 0xFF ) && ( endColor != 0xFF ) ) {
                    oldP = startColor;
                    for ( i = 1; i < (bmp.width - 24); i++ ) {
                        var tempColor:uint = tempArray[4*i+1];
                        if ( tempColor != oldP ) {
                            tempX ++;
                            oldP = tempColor;
                        }
                        if ( tempColor == 0xFF ) {
                            whiteNum++;
                        } else {
                            if ( whiteNum > 0 ) {
                                whiteArray.push( [whiteNum] );
                                whiteNum = 0;
                            }
                        }
                    }
                    var sum:Number = 0;
                    // 妥当性のチェック 白いマスが全部同じくらいのサイズだったらOK
                    for ( var k:uint = 0; k < whiteArray.length; k++ ) {
                        sum += Number( whiteArray[k] );
                    }
                    var average:Number = sum / whiteArray.length;
                    var error:uint = 0;
                    for ( k = 0; k < whiteArray.length; k++ ) {
                        if ( ! ((whiteArray[k] > (average * 0.5)) && (whiteArray[k] < (average * 1.5)) ) ) {
                            error++;
                        }
                    }
                    if ( (numX < tempX) && (error == 0) ) {
                        numX = tempX;
                    }
                }
            }
            numX = Math.floor( ( ( numX - 3 ) - 6  ) * 0.25 ) + 1;
            startTopLeft = new Point( topLeftRect.topLeft.x + topLeftRect.width, 26 );
            var numY:uint = 0;
            whiteNum = 0;
            for ( j = -8; j <= 0; j++ ) {
                tempX = 0;
                whiteArray = [];
                tempArray = bmp.getPixels( new Rectangle( startTopLeft.x + j, startTopLeft.y, 1, bmp.height - 52 ) );
                startColor = tempArray[1];
                endColor = tempArray[4*(bmp.height-26-1)+1];
                if ( ( startColor != 0xFF ) && ( endColor != 0xFF ) ) {
                    oldP = startColor;
                    for ( i = 1; i < (bmp.height - 24); i++ ) {
                        tempColor = tempArray[4*i+1];
                        if ( tempColor != oldP ) {
                            tempX ++;
                            oldP = tempColor;
                        }
                        if ( tempColor == 0xFF ) {
                            whiteNum++;
                        } else {
                            if ( whiteNum > 0 ) {
                                whiteArray.push( [whiteNum] );
                                whiteNum = 0;
                            }
                        }
                    }
                    sum = 0;
                    // 妥当性のチェック 白いマスが全部同じくらいのサイズだったらOK
                    for ( k = 0; k < whiteArray.length; k++ ) {
                        sum += Number( whiteArray[k] );
                    }
                    average = sum / whiteArray.length;
                    error = 0;
                    for ( k = 0; k < whiteArray.length; k++ ) {
                        if ( ! ((whiteArray[k] > (average * 0.5)) && (whiteArray[k] < (average * 1.5)) ) ) {
                            error++;
                        }
                    }
                    if ( (numY < tempX) && (error == 0) ) {
                        numY = tempX;
                    }
                }
            }
            numY = Math.floor( ( ( numY - 3 ) - 6  ) * 0.25 ) + 1;

            if ( (numX == numY) && (numX >= _minVersion) && (numX <= _maxVersion ) ) {
//                trace("numX");
            } else {
                numX = 0;
            }
            bmp.unlock();
            return {cellSize:(topRightRect.x + topRightRect.width - topLeftRect.x) / (numX * 4 + 17), version:numX, topLeftRect: topLeftRect, topRightRect:topRightRect, bottomLeftRect: bottomLeftRect};
        }
        /**
         * 画像中央付近の明るさを使って白と黒の閾値を計算する
         * @param bmp 画像
         * @param 閾値
         */
        private function _getThreshold( bmp:BitmapData ):uint {
            var rect:Rectangle = new Rectangle( bmp.width * 0.5, 0, 1, bmp.height );
            var bmp_check:BitmapData = new BitmapData( 1, bmp.height );
            bmp_check.copyPixels(bmp, rect, new Point(0, 0));
            bmp_check.lock();
            var tempArray:ByteArray = bmp_check.getPixels( bmp_check.rect );
            var sum:Number = 0.0;
            for ( var i:uint = 0; i < bmp.height; i++ ) {
                sum += tempArray[4*i+3]; // 緑成分で判定
            }
            sum /= bmp.height;
            
            return uint(0xFF000000 + 0x00010101 * Math.round(sum));
        }
        /**
         * 画像をグレースケール化する
         * @param bmp_src 元の画像
         * @param bmp_dst 結果格納先の画像
         * @param rect 適用範囲指定
         * @param point 適用原点指定
         * @param constnum 明るさ補正
         **/
        private function _toGray( bmp_src:BitmapData, bmp_dst:BitmapData, rect:Rectangle, point:Point, constnum:Number = 2.5 ):void {
            var conGray:Array = [constnum*0.3, constnum*0.59, constnum*0.11];
            var cmfGray:ColorMatrixFilter = new ColorMatrixFilter(
                [conGray[0], conGray[1], conGray[2], 0, 0,
                conGray[0], conGray[1], conGray[2], 0, 0,
                conGray[0], conGray[1],conGray[2], 0, 0,
                0, 0, 0, 0, 255] 
            );
            bmp_dst.applyFilter( bmp_src, rect, point, cmfGray );
        }
        /**
         * 画像を2値化する
         * @param bmp 2値化する画像
         * @param threshold 閾値
         **/
        private function _binalization( bmp:BitmapData, threshold:uint = 0xFFFFFFFF ):void {
            bmp.threshold(bmp, bmp.rect, new Point(0, 0), "<", threshold, 0xFF000000, 0xFFFFFFFF );
            bmp.threshold(bmp, bmp.rect, new Point(0, 0), ">=", threshold, 0xFFFFFFFF, 0xFFFFFFFF );
        }
        /**
         * 境界上の点をピックアップする
         * @param bmp 元画像
         * @param rect 対象画像位置
         * @param color 対象色
         * @param devide 分割個数
         * @param 点情報
         **/
        private function _getBorderPoints(bmp:BitmapData, rect:Rectangle, color:uint, divide:uint):Array {
            var tempX:uint;
            var tempY:uint;
            var tempBmpX:BitmapData = new BitmapData( rect.width, 1);
            var tempBmpY:BitmapData = new BitmapData( 1, rect.height );
            var tempRect2:Rectangle;
            var tempPoint:Point;
            var loopCount:uint = divide;
            var borderPoints:Array = new Array();
            for (var j:uint = 0; j <= loopCount; j++ ) {
                tempX = ( (rect.width-1) * j ) / loopCount + rect.topLeft.x;
                tempY = ( (rect.height-1) * j ) / loopCount + rect.topLeft.y;
                tempBmpX.copyPixels( bmp, new Rectangle(rect.topLeft.x, tempY, rect.width, 1), new Point(0,0) );
                tempBmpY.copyPixels( bmp, new Rectangle(tempX, rect.topLeft.y, 1, rect.height), new Point(0,0) );
                // 横線スキャン
                tempRect2 = tempBmpY.getColorBoundsRect( 0xFFFFFFFF, color );
                tempPoint = new Point(
                    tempX + tempRect2.topLeft.x,
                    rect.topLeft.y + tempRect2.topLeft.y
                );
                borderPoints.push( tempPoint );
                tempPoint = new Point(
                    tempX + tempRect2.topLeft.x + tempRect2.width,
                    rect.topLeft.y + tempRect2.topLeft.y + tempRect2.height );
                borderPoints.push( tempPoint );
                // 縦線スキャン
                tempRect2 = tempBmpX.getColorBoundsRect( 0xFFFFFFFF, color );
                tempPoint = new Point(
                    rect.topLeft.x + tempRect2.topLeft.x,
                    tempY + tempRect2.topLeft.y
                );
                borderPoints.push( tempPoint );
                tempPoint = new Point(
                    rect.topLeft.x + tempRect2.topLeft.x + tempRect2.width,
                    tempY + tempRect2.topLeft.y + tempRect2.height
                );
                borderPoints.push( tempPoint );
            }
            return borderPoints;
        }
    }    
}
import flash.geom.Point;

/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode */
{
    /**
     * ガロア体GF(2^w) w=4, 8 の計算に用いる定数
     */
    /* public */ internal class GFstatic
    {
        /**
         * GF(2^4)計算用定数.
         * _power2vector_4[指数] = 整数値 のように使います
         */
        public static var _power2vector_4:Array = [
            1, 2, 4, 8, 3, 6, 12, 11,
            5, 10, 7, 14, 15, 13, 9, 1
        ];
        /**
         * GF(2^4)計算用定数.
         * _power2vector_4[整数値] = 指数 のように使います
         */
        public static var _vector2power_4:Array = [
            -1, 0, 1, 4, 2, 8, 5, 10,
            3, 14, 9, 7, 6, 13, 11, 12
        ];
        /**
         * GF(2^8)計算用定数.
         * _power2vector_8[指数] = 整数値 のように使います
         */
        public static var _power2vector_8:Array = [
            1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 
            76, 152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96, 192, 
            157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35, 
            70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210, 185, 111, 222, 161, 
            95, 190, 97, 194, 153, 47, 94, 188, 101, 202, 137, 15, 30, 60, 120, 240, 
            253, 231, 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 
            217, 175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103, 206, 
            129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204, 
            133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66, 132, 21, 42, 84, 
            168, 77, 154, 41, 82, 164, 85, 170, 73, 146, 57, 114, 228, 213, 183, 115, 
            230, 209, 191, 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 
            227, 219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87, 174, 65, 
            130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 
            81, 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86, 172, 69, 138, 9, 
            18, 36, 72, 144, 61, 122, 244, 245, 247, 243, 251, 235, 203, 139, 11, 22, 
            44, 88, 176, 125, 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1
        ];
        /**
         * GF(2^8)計算用定数.
         * _power2vector_8[整数] = 指数 のように使います
         */
        public static var _vector2power_8:Array = [
            -1, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75,  
            4, 100, 224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113,  
            5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18, 130, 69,  
            29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9, 120, 77, 228, 114, 166,  
            6, 191, 139, 98, 102, 221, 48, 253, 226, 152, 37, 179, 16, 145, 34, 136,  
            54, 208, 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64,  
            30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61,  
            202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115, 243, 167, 87,  
            7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24,  
            227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217, 35, 32, 137, 46,  
            55, 63, 209, 91, 149, 188, 207, 205, 144, 135, 151, 178, 220, 252, 190, 97,  
            242, 86, 211, 171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162,  
            31, 45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111, 246,  
            108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177, 187, 204, 62, 90,  
            203, 89, 95, 176, 156, 169, 160, 81, 11, 245, 22, 235, 122, 117, 44, 215,  
            79, 174, 213, 233, 230, 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175 
        ];
    }
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode  */
{
    /* import com.logosware.utils.LabelingClass; */
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.DisplayObject;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.filters.BlurFilter;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.ConvolutionFilter;
    import flash.geom.ColorTransform;
    import flash.geom.Matrix;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.getTimer;
    
    /**
     * @author UENO Kenichi
     */
    /* public */ internal class QRCodeDetecter extends Sprite
    {
        private var image:DisplayObject;
        private var bd:BitmapData;
        private var bd2:BitmapData;
        private var threshold:uint = 0xFF888888;
        private var grayConst:Array = [
            0.3, 0.59, 0.11, 0, 0,
            0.3, 0.59, 0.11, 0, 0,
            0.3, 0.59, 0.11, 0, 0,
            0, 0, 0, 0, 255
        ];
        /**
         * 画像からQRコードを見つけ出します
         * @param    imageSource
         */
        public function QRCodeDetecter(imageSource:DisplayObject) 
        {
            image = imageSource;
            bd = new BitmapData(image.width, image.height, true, 0x0);
            bd2 = new BitmapData(image.width, image.height, true, 0x0);
// debug code
/*
            var bmp:Bitmap = new Bitmap( bd );
            image.parent.addChild( bmp );
            bmp.x = image.width;
*/
        }
        /**
         * 見つかったQRコードの位置情報を返します
         * @return マーカー配列
         *     [
         *         {
         *             image:BitmapData,
         *             borderColors:[
         *                 0: uint color of topleft marker
         *                 1: uint color of topright marker
         *                 2: uint color of bottomleft marker
         *             ],
         *             originalLocation:[
         *                 0: Rectangle of topleft marker
         *                 1: Rectangle of topright marker
         *                 2: Rectangle of bottomleft marker
         *             ]
         *         }
         *         ...
         *     ]
         */
        public function detect():Array {
            var ret:Array = [];
            bd.lock();
            bd.draw(image);
            
            // グレー化
            bd.applyFilter(bd, bd.rect, new Point(), new ColorMatrixFilter(grayConst));
            bd.applyFilter(bd, bd.rect, new Point(), new ConvolutionFilter(5, 5, [
                0, -1, -1, -1, 0,
                -1, -1, -2, -1, -1,
                -1, -2, 25, -2, -1,
                -1, -1, -2, -1, -1,
                0, -1, -1, -1, 0
            ]));
            bd.applyFilter(bd, bd.rect, new Point(), new BlurFilter(3, 3));
            
            // 二値化
            bd.threshold(bd, bd.rect, new Point(), ">", threshold, 0xFFFFFFFF, 0x0000FF00);
            bd.threshold(bd, bd.rect, new Point(), "!=", 0xFFFFFFFF, 0xFF000000);
            
            // ラベリング
            var LabelingObj:LabelingClass = new LabelingClass(); 
            LabelingObj.Labeling( bd, 10, 0xFF88FFFE, true ); // ラベリング実行
            
            var pickedRects:Array = LabelingObj.getRects();
            var pickedColor:Array = LabelingObj.getColors();
            
            LabelingObj = null;
            
            // マーカー候補の矩形を取得
            var borders:Array = _searchBorders( bd, pickedRects, pickedColor );
            
            // 直角の位置にあるコードを検索
            var codes:Array = _searchCode( borders );
            
            // 適切な角度で切り抜き
            var images:Array = _clipCodes( bd, codes );
            
            for ( var i:int = 0; i < images.length; i++ ) {
                ret.push( { image:images[i], borderColors:[codes[i][0].borderColor, codes[i][1].borderColor, codes[i][2].borderColor], originalLocation:[codes[i][0].borderRect, codes[i][1].borderRect, codes[i][2].borderRect] } );
            }
            bd.unlock();
            return ret;
        }
        private function _clipCodes( bd:BitmapData, codes:Array):Array {
            var ret:Array = [];
            for ( var i:int = 0; i < codes.length; i++ ) {
                var marker1:Rectangle = codes[i][0].borderRect; // top left
                var marker2:Rectangle = codes[i][1].borderRect; // top right
                var marker3:Rectangle = codes[i][2].borderRect; // bottom left
                var vector12:Point = marker2.topLeft.subtract( marker1.topLeft ); // vector: top left -> top right
                var vector13:Point = marker3.topLeft.subtract( marker1.topLeft ); // vector: top left -> bottom left
                var theta:Number = -Math.atan2( vector12.y, vector12.x ); // 平面状の回転角
                
                var matrix:Matrix = new Matrix();
                var d:Number = (0.5 * marker1.width) / (Math.abs(Math.cos( theta )) + Math.abs(Math.sin( theta ) ) ); // マーカーの一辺の長さの半分
                
                matrix.translate( -(marker1.topLeft.x + marker1.width * 0.5), -(marker1.topLeft.y + marker1.height * 0.5) );
                matrix.rotate( theta );
                matrix.translate( 20 + d, 20 + d );
                
                var matrix2:Matrix = new Matrix();
                matrix2.rotate( theta );
                var vector13r:Point = matrix2.transformPoint( vector13 );
                
                matrix2 = new Matrix(1.0, 0, -vector13r.x/vector13r.y, vector12.length / vector13r.y );
                
                matrix.concat( matrix2 );
                
                var len:Number = ( vector12.length + 2 * d ); // QRコードの一辺の長さ
                var bd2:BitmapData = new BitmapData( 40 + len, 40 + len );
                bd2.draw( bd, matrix );
                ret.push( bd2 );
            }
            return ret;
        }
        /**
         * マーカーの候補をピックアップする
         * @param    bmp ラベリング済みの画像
         * @param    rectArray 矩形情報
         * @param    colorArray 矩形の色情報
         * @return 候補の配列
         */
        private function _searchBorders(bmp:BitmapData, rectArray:Array, colorArray:Array):Array {
            function isMarker( ary:Array ):Boolean {
                var c:Number = 0.75;
                var ave:Number = (ary[0] + ary[1] + ary[2] + ary[3] + ary[4]) / 7;
                return(
                    ary[0] > ((1.0-c)*ave) && ary[0] < ((1.0+c)*ave) &&
                    ary[1] > ((1.0-c)*ave) && ary[1] < ((1.0+c)*ave) &&
                    ary[2] > ((3.0-c)*ave) && ary[2] < ((3.0+c)*ave) &&
                    ary[3] > ((1.0-c)*ave) && ary[3] < ((1.0+c)*ave) &&
                    ary[4] > ((1.0-c) * ave) && ary[4] < ((1.0+c) * ave)
                );
            }
            var retArray:Array = [];
            for ( var i:int = 0; i < rectArray.length; i++ ) {
                var count:int = 0;
                var target:Number = 0;
                var tempRect:Rectangle = rectArray[i];// 外側
                if( colorArray[i] != bmp.getPixel( rectArray[i].topLeft.x + rectArray[i].width*0.5, rectArray[i].topLeft.y + rectArray[i].height*0.5) ){
                    var oldFlg:uint = 0;
                    var tempFlg:uint = 0;
                    var index:int = -1;
                    var countArray:Array = [0.0, 0.0, 0.0, 0.0, 0.0];
                    var j:int;
                    var constNum:Number;

                    // 横方向
                    constNum = rectArray[i].topLeft.y + rectArray[i].height*0.5;
                    for ( j = 0; j < rectArray[i].width; j++ ){
                        tempFlg = (bmp.getPixel( rectArray[i].topLeft.x + j, constNum ) == 0xFFFFFF)?0:1;
                        if( (index == -1) && (tempFlg == 0) ){
                            //go next
                        } else {
                            if( tempFlg != oldFlg ){
                                index++;
                                oldFlg = tempFlg;
                                if( index >= 5 ){
                                    break;
                                }
                            } 
                            countArray[index]++;
                        }
                    }

                    if ( isMarker(countArray) ) {
                        // 縦方向
                        countArray = [0.0, 0.0, 0.0, 0.0, 0.0];
                        oldFlg = tempFlg = 0;
                        index = -1;

                        constNum = rectArray[i].topLeft.x + rectArray[i].width*0.5;
                        for ( j = 0; j < rectArray[i].width; j++ ) {
                            tempFlg = (bmp.getPixel( constNum, rectArray[i].topLeft.y + j ) == 0xFFFFFF)?0:1;
                            if( (index == -1) && (tempFlg == 0) ){
                                //go next
                            } else {
                                if( tempFlg != oldFlg ){
                                    index++;
                                    oldFlg = tempFlg;
                                    if( index >= 5 ){
                                        break;
                                    }
                                } 
                                countArray[index]++;
                            }
                        }
                        if ( isMarker(countArray) ) {
                            retArray.push( {borderColor:colorArray[i], borderRect:rectArray[i]} );
                        }
                    }

                }
            }
            return retArray;
        }
        /**
         * 直角関係にあるマーカーを探します
         * @param    borders 候補の配列
         * @return
         */
        private function _searchCode( borders:Array ):Array {
            function isNear( p1:Point, p2:Point, d:Number ):Boolean {
                return(
                    (p1.x + d) > p2.x &&
                    (p1.x - d) < p2.x &&
                    (p1.y + d) > p2.y &&
                    (p1.y - d) < p2.y
                );
            }
            var ret:Array = [];
            var loop:int = borders.length;
            for ( var i:int = 0; i < (loop-2); i++ ) {
                for ( var j:int = i + 1; j < (loop-1); j++ ) {
                    var vec:Point = borders[i].borderRect.topLeft.subtract( borders[j].borderRect.topLeft );
                    for ( var k:int = j + 1; k < loop; k++ ) {
                        if( isNear( borders[k].borderRect.topLeft, new Point( borders[i].borderRect.topLeft.x + vec.y, borders[i].borderRect.topLeft.y - vec.x ), 0.125 * vec.length ))
                            ret.push( [borders[i], borders[j], borders[k]] );
                        else if ( isNear( borders[k].borderRect.topLeft, new Point( borders[i].borderRect.topLeft.x - vec.y, borders[i].borderRect.topLeft.y + vec.x ), 0.125 * vec.length ))
                            ret.push( [borders[i], borders[k], borders[j]] );
                        else if ( isNear( borders[k].borderRect.topLeft, new Point( borders[j].borderRect.topLeft.x + vec.y, borders[j].borderRect.topLeft.y - vec.x ), 0.125 * vec.length ))
                            ret.push( [borders[j], borders[k], borders[i]] );
                        else if ( isNear( borders[k].borderRect.topLeft, new Point( borders[j].borderRect.topLeft.x - vec.y, borders[j].borderRect.topLeft.y + vec.x ), 0.125 * vec.length ))
                            ret.push( [borders[j], borders[i], borders[k]] );
                    }
                }
            }
            return ret;
        }
    }
    
}/**************************************************************************
* LOGOSWARE Class Library.
*
* Copyright 2009 (c) LOGOSWARE (http://www.logosware.com) All rights reserved.
*
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/ 
/* package com.logosware.utils.QRcode */
{
    /* import com.logosware.event.QRdecoderEvent; */
    
    import flash.events.EventDispatcher;
    import flash.system.System;
    import flash.text.TextField;
    import flash.utils.unescapeMultiByte;

    /**
     * QRコードをデコードして文字列を抽出するクラスです
     * @author Kenichi UENO
     **/
    /* public */ internal class QRdecode extends EventDispatcher {
        private var _xorPattern:Array = [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0];
        private var _fixed:Array;
        private var _qr:Array;
//        private var _textObj:TextField = new TextField();
        private var _qrVersion:uint = 5;
        public function QRdecode() {
        }
        /**
         * 解析したいQRコードを格納する関数
         * @param qr QRコードのビットパターン二次元配列
         */
        public function setQR( qr:Array ):void {
            _qr = qr;
            _qrVersion = (qr.length - 17) * 0.25;
        }
        /**
         * setQRで格納したQRコードのデコードを行う関数
         * @param retObj 結果イベントに含ませたいオブジェクト
         * @eventType QRdecoderEvent.QR_DECODE_COMPLETE
         */
        public function startDecode(retObj:Object = null):void {
            // 形式情報の読み出し
            var dataArray:Array;
            var unmaskedQR:Array;
            var wordArray:Array;
            var trueWordArray:Array;
            var result:Array;
            var resultFlg:uint;
            var resultStr:String;
            var qrSize:uint = _qrVersion * 4 + 17;
            dataArray = _decode15_5(); 
            // マスク処理の解除
            unmaskedQR = _unmask( dataArray );
            // 機能領域の計算
            _makeFixed();
            // データ読み出し
            wordArray = _getWords( unmaskedQR );
            // リードソロモン
            trueWordArray = _ReedSolomon( wordArray, dataArray );            
            //データコード語復号
            result = _readData( trueWordArray );
            resultFlg = result[0];
            if ( resultFlg ) {
                resultStr = result[1];
//                _textObj.appendText( "読み取り成功!\n" + resultStr );
                dispatchEvent( new QRdecoderEvent( QRdecoderEvent.QR_DECODE_COMPLETE, resultStr, [retObj] ) ); 
            }
        }
        /**
         * リードソロモンで8bitずつ読み取る関数
         */
        private function _RS8bit( __dataArray:Array, __codeNum:uint, __errorNum:uint, __snum:uint ):void {
            var __i:uint;
            var __j:uint;
            var __index:uint;
            var __dataLength:uint = __dataArray.length;
            var __Snum:uint = __errorNum;
            var __a:Array; // 誤り位置計算用変数
            var __e:Array; // 誤り位置
            var __S:Array = new Array(__Snum); // シンドローム
            var __s:Array = new Array(__snum); // 誤り位置変数
            var __tempNum1:G8Num;
            var __tempNum2:G8Num;
            
            // シンドローム配列初期化
            for ( __j = 0; __j < __Snum; __j++ ) {
                __S[__j] = new G8Num(-1);
            }

            for ( __i = 0; __i < __dataLength; __i++ ) {
                __tempNum1 = new G8Num(0);
                __tempNum1.setVector( __dataArray[__dataLength - 1 - __i] );
                    for ( __j = 0; __j < __Snum; __j++ ) {
                        __S[__j] = __S[__j].plus( __tempNum1.multiply(new G8Num( __i * __j )) );
                    }
            }
            __j = 0;
            for ( __i = 0; __i < __Snum; __i++ ) {
                if( __S[__i].getPower() != -1 ){
                    __j++;
                }
            }
            if( __j == 0 ){ // 100%エラーなし
                return;
            }
            // エラーあるかも
            for ( __i = __snum; __i > 0; __i-- ){
                if( _calcDet( __S, __i ) != 0 ){
                    break;
                }
            }
            
            __snum = __i;
            __a = new Array(__snum);

            // 誤り訂正位置変数の計算
            for (__i = 0; __i < __snum; __i++) {
                __a[__i] = new Array(__snum+1);
                for (__j = 0; __j <= __snum; __j++ ) {
                    __a[__i][__j] = new G8Num( __S[__i+__j].getPower() );
                }
            }
            for ( __i = 0; __i < __snum; __i++ ){
                _reduceToLU( __a, __i );
            }
            for (__i = 0; __i < __snum; __i++) {
                for ( __j = 0; __j < __snum; __j++ ) {
                    if (__a[__i][__j].getPower() != -1) {
                        __s[__snum-1-__j] = __a[__i][__snum];
                    }
                }
            }

            //__aは再利用
            __e = new Array( __snum );
            __index = 0;
            for ( __i = 0; __i < __dataLength; __i++ ) {
                __tempNum1 = new G8Num( __i * __snum );
                
                for ( __j = __snum - 1; __j >= 1; __j-- ) {
                    __tempNum2 = new G8Num( __i * __j );
                    __tempNum1 = __tempNum1.plus( __tempNum2.multiply( __s[__snum-1-__j] ) );
                }

                __tempNum1 = __tempNum1.plus( __s[__snum-1] );
                
                if ( __tempNum1.getPower() < 0 ) {
                    __e[__index] = __dataLength - 1 - __i;
                    for( __j = 0; __j < __snum; __j++ ){
                        __a[__j][__index] = new G8Num(__i * __j);
                    }
                    __a[__index][__snum] = new G8Num( __S[__index].getPower() );
                    __index++;
                    
                }
            }
            
            for ( __i = 0; __i < __snum; __i++ ){
                _reduceToLU( __a, __i );
            }
            for ( __i = 0; __i < __snum; __i++ ){
                for ( __j = 0; __j < __snum; __j++ ){
                    if( __a[__i][__j].getPower() == 0 ){
                        __dataArray[__e[__j]] = __dataArray[__e[__j]] ^ (__a[__i][__snum].getVector() );
                    }
                }
            }
        }
        /**
         * 行列式を計算する
         * @param 行列
         * @param 行列サイズ
         **/
        private function _calcDet( __Dat:Array, __size:uint ):int {
            var __i:uint;
            var __j:uint;
            var __k:uint;
            var __doing:uint = 0;
            var __result:G8Num = new G8Num(0);
            var __tempNum:G8Num;
            var __todo:Array = new Array( __size );
            var __temp:Array = new Array( __size );
            for( __j = 0; __j < __size; __j++ ){
                __todo[__j] = 1;
                __temp[__j] = new Array( __size );
                for ( __i = 0; __i < __size; __i++ ){
                    __temp[__j][__i] = new G8Num( __Dat[__i+__j].getPower() );
                }
            }
            //三角行列にする
            while( __doing < __size ){ // 一列ずつ、つぶす
                for( __i = 0; __i < __size; __i++ ){
                    if( __todo[__i] == 1 ){
                        if( __temp[__i][__doing].getPower() >= 0 ){
                            __result.multiply( __temp[__i][__doing] );
                            __tempNum = __temp[__i][__doing].inverse();
                            //自身の列の頭を1に
                            for( __j = __doing; __j < __size; __j++ ){
                                __temp[__i][__j] = __temp[__i][__j].multiply( __tempNum );
                            }
                            //その他の列を全部引き算
                            for( __k = 0; __k < __size; __k++ ){
                                if( (__k != __i) && (__todo[__k] == 1) && (__temp[__k][__doing].getPower() >= 0) ){
                                    __tempNum = new G8Num(__temp[__k][__doing].getPower() );
                                    for( __j = __doing; __j < __size; __j++ ){
                                        __temp[__k][__j] = __temp[__k][__j].plus( __tempNum.multiply( __temp[__i][__j] ) );
                                    }
                                }
                            }
                            __todo[__i] = 0;
                            break;
                        }
                    }
                }
                if( __i == __size ){
                    return 0;
                }
                __doing++;
            }
            return __result.getVector();
        }
        /**
         * 下三角行列を作る
         */
        private function _reduceToLU(__a:Array, __num:uint ):void {
            var __i:uint;
            var __j:uint;
            var __it:uint;
            var __flg:uint;
            var __snum:uint = __a.length;
            var __tempNum:G8Num;
            
            for ( __i = 0; __i < __snum; __i++ ) {
                __flg = 0;
                if ( __a[__i][__num].getPower() != -1 ) {
                    __flg = 1;
                    for ( __j = 0; __j < __num; __j++ ) {
                        if ( __a[__i][__j].getPower() != -1 ) {
                            __flg = 0;
                        }
                    }
                }
                if ( __flg ) {
                    __it = __i;
                    __i = __snum;
                }
            }
            __tempNum = __a[__it][__num].inverse();
            for ( __j = __num; __j <= __snum; __j++ ) {
                __a[__it][__j] = __a[__it][__j].multiply( __tempNum );
            }
            for ( __i = 0; __i < __snum; __i++ ) {
                if ( (__i != __it) && (__a[__i][__num].getPower != -1 ) ) {
                    __tempNum = new G8Num( __a[__i][__num].getPower() );
                    for ( __j = __num; __j <= __snum; __j++ ) {
                        __a[__i][__j] = __a[__i][__j].plus( __a[__it][__j].multiply( __tempNum ) );
                    }
                }    
            }
        }
        /**
         * バイナリを文字列に変換する
         * @param バイナリデータ
         */
        private function _readData ( __dataCode:Array ):Array {
            var __num2alphabet:Array = [
                "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
                "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
                "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
                "U", "V", "W", "X", "Y", "Z", " ", "$", "%", "*",
                "+", "-", ".", "/", ":"
            ];
            var __verMode:uint;
            var __stringBits:Array = [[10,9,8,8],[12,11,16,10],[14,13,16,12]];
            var __result:String = "";
            var __dataBin:Array;
            var __i:uint;
            var __mode:String;
            var __num:uint;
            var __tempNum:uint;
            var __tempNum2:uint;
            var __tempStr:String;
            var __isSuccess:uint = 1;
            
            if( _qrVersion < 10 ){
                __verMode = 0;
            } else if( _qrVersion < 27 ) {
                __verMode = 1;
            } else if( _qrVersion < 41 ) {
                __verMode = 2;
            }
            
            __dataBin = _Hex2Bin( __dataCode );
            //どんどん読み取り
            while( __dataBin.length > 0 ){
                __mode = _readNstr( __dataBin, 4 );
                switch( __mode ) {
                    case "0001": // 数字
                            __num = _readNnumber( __dataBin, __stringBits[__verMode][0] ); // 10: バージョンに依存
                            for ( __i = 0; __i < __num; __i += 3 ) {
                                if ( (__num - __i) == 2 ) {
                                    __tempNum = _readNnumber( __dataBin, 7 );
                                    __result += String("00"+__tempNum).substr(-2,2);
                                } else if( (__num - __i) == 1 ) {
                                    __tempNum = _readNnumber( __dataBin, 4 );
                                    __result += String("0"+__tempNum).substr(-1,1);
                                } else {
                                    __tempNum = _readNnumber( __dataBin, 10 );
                                    __result += String("000"+__tempNum).substr(-3,3);
                                }
                            }
                        break;
                    case "0010": // 英数字
                            __num = _readNnumber( __dataBin, __stringBits[__verMode][1] ); // 9: バージョンに依存
                            for ( __i = 0; __i < __num; __i += 2 ) {
                                if ( (__num - __i) > 1 ) {
                                    __tempNum = _readNnumber( __dataBin, 11 );
                                    __result += __num2alphabet[ Math.floor(__tempNum / 45) ] + __num2alphabet[ __tempNum % 45 ];
                                } else {
                                    __tempNum = _readNnumber( __dataBin, 6 );
                                    __result += __num2alphabet[ __tempNum ];
                                }
                            }
                        break;
                    case "0100": // 8 bit Byte
                            __num = _readNnumber( __dataBin, __stringBits[__verMode][2] ); // 8: バージョンに依存
                            __tempStr = "";
                            for ( __i = 0; __i < __num; __i ++ ) {
                                __tempNum = _readNnumber( __dataBin, 8 );
                                
//                                __result += String.fromCharCode(__tempNum);
                                __tempStr += "%"+_Hex2String(__tempNum);
                            }
                                System.useCodePage = true;
                            __result += unescapeMultiByte( __tempStr );
                            
                        break;
                    case "1000": // 漢字
                            __num = _readNnumber( __dataBin, __stringBits[__verMode][3] ); // 8: バージョンに依存
                            for ( __i = 0; __i < __num; __i ++ ) {
                                __tempNum = _readNnumber( __dataBin, 13 );
                                __tempNum2 = Math.floor(__tempNum / 0xC0 );
                                __tempNum2 += ( __tempNum2 <= 0x1E )?0x81:0xC1;
                                __tempNum %= 0xC0;
                                __tempNum += 0x40;
                                System.useCodePage = true;
                                __result += unescapeMultiByte( "%"+_Hex2String(__tempNum2)+"%"+_Hex2String(__tempNum) );
//                                __result += "("+_Hex2String(__tempNum2)+_Hex2String(__tempNum)+")";
                            }
                        break;
                    case "0000":
                    case "000":
                    case "00":
                    case "0":
                            __tempNum = _readNnumber( __dataBin, __dataBin.length );
                            //正常終了
                        break;
                    default: //未対応
                            __isSuccess = 0;
                            __result += "***未対応の形式を検出しました。";
                            continue;
                        break;
                }
            }
            return [__isSuccess, __result];
        }
        /**
         * 32ビットのデータを文字に直す
         * @param バイナリデータ
         */
        private function _Hex2String( __hex:uint ):String {
            var __tempNum:uint = __hex >> 4;
            var __tempNum2:uint = __hex & 0xF;
            return String.fromCharCode( __tempNum+48 + uint(__tempNum>9)*7  )+String.fromCharCode( __tempNum2+48 + uint(__tempNum2>9)*7  );
                
        }
        /**
         * N文字分の文字列を読み込む
         * @param バイナリデータ
         * @param データ長
         */
        private function _readNstr( __bin:Array, __length:uint ):String {
            var __i:uint;
            var __retStr:String = "";
            if ( __bin.length < __length ) {
                __length = __bin.length;
            }
            for ( __i = 0; __i < __length; __i++ ) {
                __retStr += __bin[0]? "1":"0";
                __bin.shift();
            }
            return __retStr;
        }
        /**
         * N文字分の数字を読み込む
         * @param バイナリデータ
         * @param データ長
         */
        private function _readNnumber( __bin:Array, __length:uint ):uint {
            var __i:uint;
            var __retNum:uint = 0;
            for ( __i = 0; __i < __length; __i++ ) {
                __retNum <<= 1;
                __retNum += __bin[0];
                __bin.shift();
            }
            return __retNum;
        }
        /**
         * 16進数の配列を2進数の配列に直す
         * @param 16進数パターン
         */
        private function _Hex2Bin( __hex:Array ):Array {
            var __i:uint;
            var __index:uint;
            var __loopCount:uint = __hex.length;
            var __retArray:Array = new Array( __loopCount * 8 );
            for ( __i = 0; __i < __loopCount; __i++ ) {
                __retArray[__index++] = (__hex[__i]>>7) & 1;
                __retArray[__index++] = (__hex[__i]>>6) & 1;
                __retArray[__index++] = (__hex[__i]>>5) & 1;
                __retArray[__index++] = (__hex[__i]>>4) & 1;
                __retArray[__index++] = (__hex[__i]>>3) & 1;
                __retArray[__index++] = (__hex[__i]>>2) & 1;
                __retArray[__index++] = (__hex[__i]>>1) & 1;
                __retArray[__index++] = (__hex[__i]>>0) & 1;
            }
            return __retArray;
        }
        /**
         * リードソロモン解析
         * @param 解析データ
         * @param 形式情報
         */
        private function _ReedSolomon( __data:Array, __type:Array ):Array {
            var __RSblock:Array;
            var __retArray:Array = [];
            var __dataNum:Array;
            var __errorNum:Array;
            var __i:uint;
            var __loopCount:uint;
            var __j:uint;
            var __loopCount2:uint;
            var __index:uint = 0;
            var __correctNum:uint = 0;
            switch( _qrVersion ) {
                case 1:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(1);
                                    __dataNum = [16];
                                    __errorNum = [10];
                                break;
                            case 1: // L
                                    __RSblock = new Array(1);
                                    __dataNum = [19];
                                    __errorNum = [7];
                                break;
                            case 2: // H
                                    __RSblock = new Array(1);
                                    __dataNum = [9];
                                    __errorNum = [17];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(1);
                                    __dataNum = [13];
                                    __errorNum = [13];
                                break;
                        }
                    break;
                case 2:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(1);
                                    __dataNum = [28];
                                    __errorNum = [16];
                                break;
                            case 1: // L
                                    __RSblock = new Array(1);
                                    __dataNum = [34];
                                    __errorNum = [10];
                                break;
                            case 2: // H
                                    __RSblock = new Array(1);
                                    __dataNum = [16];
                                    __errorNum = [28];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(1);
                                    __dataNum = [22];
                                    __errorNum = [22];
                                break;
                        }
                    break;
                case 3:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(1);
                                    __dataNum = [44];
                                    __errorNum = [26];
                                break;
                            case 1: // L
                                    __RSblock = new Array(1);
                                    __dataNum = [55];
                                    __errorNum = [15];
                                break;
                            case 2: // H
                                    __RSblock = new Array(2);
                                    __dataNum = [13,13];
                                    __errorNum = [22,22];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(2);
                                    __dataNum = [17,17];
                                    __errorNum = [18,18];
                                break;
                        }
                    break;
                case 4:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(2);
                                    __dataNum = [32,32];
                                    __errorNum = [18,18];
                                break;
                            case 1: // L
                                    __RSblock = new Array(1);
                                    __dataNum = [80];
                                    __errorNum = [20];
                                break;
                            case 2: // H
                                    __RSblock = new Array(4);
                                    __dataNum = [9,9,9,9];
                                    __errorNum = [16,16,16,16];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(2);
                                    __dataNum = [24,24];
                                    __errorNum = [26,26];
                                break;
                        }
                    break;
                case 5:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(2);
                                    __dataNum = [43, 43];
                                    __errorNum = [24, 24];
                                break;
                            case 1: // L
                                    __RSblock = new Array(1);
                                    __dataNum = [108];
                                    __errorNum = [26];
                                break;
                            case 2: // H
                                    __RSblock = new Array(4);
                                    __dataNum = [11, 11, 12, 12];
                                    __errorNum = [22, 22, 22, 22];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(4);
                                    __dataNum = [15, 15, 16, 16];
                                    __errorNum = [18, 18,18,18];
                                break;
                        }
                    break;
                case 6:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(4);
                                    __dataNum = [27, 27, 27, 27];
                                    __errorNum = [16, 16, 16, 16];
                                break;
                            case 1: // L
                                    __RSblock = new Array(2);
                                    __dataNum = [68, 68];
                                    __errorNum = [18, 18];
                                break;
                            case 2: // H
                                    __RSblock = new Array(4);
                                    __dataNum = [15, 15, 15, 15];
                                    __errorNum = [28, 28, 28, 28];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(4);
                                    __dataNum = [19, 19, 19, 19];
                                    __errorNum = [24, 24, 24, 24];
                                break;
                        }
                    break;
                case 7:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(4);
                                    __dataNum = [31, 31, 31, 31];
                                    __errorNum = [18, 18, 18, 18];
                                break;
                            case 1: // L
                                    __RSblock = new Array(2);
                                    __dataNum = [78, 78];
                                    __errorNum = [20, 20];
                                break;
                            case 2: // H
                                    __RSblock = new Array(5);
                                    __dataNum = [13,13,13,13,14];
                                    __errorNum = [26,26,26,26,26];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(6);
                                    __dataNum = [14,14,15,15,15,15];
                                    __errorNum = [18,18,18,18,18,18];
                                break;
                        }
                    break;
                case 8:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(4);
                                    __dataNum = [38, 38, 39, 39];
                                    __errorNum = [22, 22, 22, 22];
                                break;
                            case 1: // L
                                    __RSblock = new Array(2);
                                    __dataNum = [97, 97];
                                    __errorNum = [24, 24];
                                break;
                            case 2: // H
                                    __RSblock = new Array(6);
                                    __dataNum = [14, 14, 14, 14, 15, 15];
                                    __errorNum = [26, 26, 26, 26, 26, 26];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(6);
                                    __dataNum = [18, 18, 18, 18, 19, 19];
                                    __errorNum = [22, 22, 22, 22, 22, 22];
                                break;
                        }
                    break;
                case 9:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(5);
                                    __dataNum = [36, 36, 36, 37, 37];
                                    __errorNum = [22, 22, 22, 22, 22];
                                break;
                            case 1: // L
                                    __RSblock = new Array(2);
                                    __dataNum = [116, 116];
                                    __errorNum = [30, 30];
                                break;
                            case 2: // H
                                    __RSblock = new Array(8);
                                    __dataNum = [12, 12, 12, 12, 13, 13, 13, 13];
                                    __errorNum = [24, 24, 24, 24, 24, 24, 24, 24];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(8);
                                    __dataNum = [16, 16, 16, 16, 17, 17, 17, 17];
                                    __errorNum = [20, 20, 20, 20, 20, 20, 20, 20];
                                break;
                        }
                    break;
                case 10:
                        switch( (__type[0] << 1) + (__type[1] << 0) ) {
                            case 0: // M
                                    __RSblock = new Array(5);
                                    __dataNum = [43, 43, 43, 43, 44];
                                    __errorNum = [26, 26, 26, 26, 26];
                                break;
                            case 1: // L
                                    __RSblock = new Array(4);
                                    __dataNum = [68, 68, 69, 69];
                                    __errorNum = [18, 18, 18, 18];
                                break;
                            case 2: // H
                                    __RSblock = new Array(8);
                                    __dataNum = [15, 15, 15, 15, 15, 15, 16, 16];
                                    __errorNum = [28, 28, 28, 28, 28, 28, 28, 28];
                                break;
                            case 3: // Q
                                    __RSblock = new Array(8);
                                    __dataNum = [19, 19, 19, 19, 19, 19, 20, 20];
                                    __errorNum = [24, 24, 24, 24, 24, 24, 24, 24];
                                break;
                        }
                    break;
                default:
//trace( _qrVersion + ", " + (__type[0] << 1) + (__type[1] << 0) );
                        return [];
                    break
            }
            __loopCount = __RSblock.length;
            for ( __i = 0; __i < __loopCount; __i++) {
                __RSblock[__i] = new Array();
            }
            __loopCount2 = __dataNum[__loopCount-1];
            for ( __j = 0; __j < __loopCount2; __j++) {
                for ( __i = 0; __i < __loopCount; __i++) {
                    // ここに条件をいれないといけない気がする。 j < datanum    とか
                    if( __j < __dataNum[__i] ){
                        __RSblock[__i].push( [ _readByteData(__data[__index++]) ] );
                    }
                }
            }
            __correctNum = __errorNum[0] * 0.5;
            if( _qrVersion == 1 ){
                switch( (__type[0] << 1) + (__type[1] << 0) ){
                    case 0:
                            __correctNum = 4;
                        break;
                    case 1:
                            __correctNum = 2;
                        break;
                    case 2:
                            __correctNum = 8;
                        break;
                    case 3:
                            __correctNum = 6;
                        break;
                }
            }
            if( (_qrVersion == 2) && ( ( (__type[0] << 1) + (__type[1] << 0) ) == 1 ) ){
                __correctNum = 4;
            }
            if( (_qrVersion == 3) && ( ( (__type[0] << 1) + (__type[1] << 0) ) == 1 ) ){
                __correctNum = 7;
            }
            
            __loopCount2 = __errorNum[0]; // 全部同じなので[0]
            for ( __j = 0; __j < __loopCount2; __j++) {
                for ( __i = 0; __i < __loopCount; __i++) {
                    __RSblock[__i].push( [ _readByteData(__data[__index++]) ] );
                }
            }
            //誤り訂正
            for ( __i = 0; __i < __loopCount; __i++ ) {
                _RS8bit( __RSblock[__i], __dataNum[__i], __errorNum[__i], __correctNum );
            }
            
            
            //データ再配置
            for ( __i = 0; __i < __loopCount; __i++) {
                __loopCount2 = __dataNum[__i];
                for ( __j = 0; __j < __loopCount2; __j++) {
                    __retArray.push(__RSblock[__i][__j]);
                }
            }
            return __retArray;
        }
        /**
         * 1バイト分の情報を読み込む
         * @param 情報ビット列
         */
        private function _readByteData( __byte:Array ):uint {
            return (__byte[0] << 7) + (__byte[1] << 6) + (__byte[2] << 5) + (__byte[3] << 4) + (__byte[4] << 3) + (__byte[5] << 2) + (__byte[6] << 1) + (__byte[7] << 0) ;
        }
        /**
         * 情報のバイト列を読み取る
         * @param QRコードビットパターン
         */
        private function _getWords( __qr:Array ):Array {
            var __checkArray:Array = [];
            var __cordNum:Array = [
                26, 44, 70, 100, 134, 172, 196, 242, 292, 346,
                404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,
                1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,
                2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706
            ]; // バージョン1~40までの総コード語数
            var __retArray:Array = new Array( __cordNum[_qrVersion - 1] );
            var __i:uint;
//            var __j:uint;
            var __loopCount:uint = __retArray.length;
            var __x:uint = _qrVersion*4 + 16;
            var __y:uint = _qrVersion*4 + 16;
            var __len:uint;
            var __toUp:uint = 1;
            var __toLeft:uint = 1;
            var __index:uint = 0;
            for ( __i = 0; __i < __loopCount; __i++ ) {
                __retArray[__i] = new Array(8);
                __checkArray[__i] = new Array(8);
//                for( __j = 0; __j < 8; __j++ ){
//                    __checkArray[__i][__j] = new Array(2);
//                }
            }
            for ( __i = 0; __i < __loopCount; __i++ ) {
                for ( __len = 0; __len < 8; __len++ ) {
                    while ( _isFixed(__x, __y) ) {
                        if ( __x == 6 ){
                            __x--;
                        }
                        if ( __toLeft ) {
                            __x--;
                            __toLeft = 0;
                        } else {
                            __toLeft = 1;
                            if ( __toUp ) {
                                if ( __y == 0 ) {
                                    __x--;
                                    __toUp = 0;
                                } else {
                                    __x++;
                                    __y--;
                                }
                            } else {
                                if ( __y == (_qrVersion*4+16) ) {
                                    __x--;
                                    __toUp = 1;
                                } else {
                                    __x++;
                                    __y++;
                                }
                            }
                        }
                    }
                    _fixed[__y][__x] = 1;
                    __retArray[__index][__len] = __qr[__y][__x];
                    __checkArray[__index][__len] = [__x, __y];
                }
                __index++;
            }
            return __retArray;
        }
        /**
         * QRコードのマスクを解除する関数
         * @param 形式情報
         */
        private function _unmask( __typeData:Array ):Array {
            var __qrSize:uint = _qrVersion * 4 + 17;
            var __retArray:Array = new Array(__qrSize);
            var __i:uint;
            var __j:uint;
            for ( __j = 0; __j < __qrSize; __j++ ) {
                __retArray[__j] = new Array(__qrSize);
            }
            switch( (__typeData[2]<<2)+(__typeData[3]<<1)+(__typeData[4]) ) {
                case 0: //(i+j)mod2==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( (__i + __j) % 2) == 0 );
                            }
                        }
                    break;
                case 1: // i mod2==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( __i % 2) == 0 );
                            }
                        }
                    break;
                case 2: //j mod3==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( __j % 3) == 0 );
                            }
                        }
                    break;
                case 3: //(i+j)mod3==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( (__i + __j) % 3) == 0 );
                            }
                        }
                    break;
                case 4: //((idiv2)+(jdiv3))mod2==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( (Math.floor(__i*0.5) + Math.floor(__j/3.0)) % 2) == 0 );
                            }
                        }
                    break;
                case 5: //((ij)mod2+(ij)mod3)==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( ( (__i*__j) % 2 ) + ((__i*__j) % 3 ) ) == 0 );
                            }
                        }
                    break;
                case 6: //((ij)mod2+(ij)mod3)mod2==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( ( ( (__i*__j) % 2 ) + ((__i*__j) % 3 ) ) % 2 ) == 0 );
                            }
                        }
                    break;
                case 7: //((i+j)mod2+(ij)mod3)mod2==0
                        for ( __j = 0; __j < __qrSize; __j++ ) {
                            for ( __i = 0; __i < __qrSize; __i++ ) {
                                __retArray[__i][__j] = _getQR(__j, __i) ^ int( ( ( ( (__i+__j) % 2 ) + ((__i*__j) % 3 ) ) % 2 ) == 0 );
                            }
                        }
                    break;
            }
            return __retArray;
        }
        /**
         * 機能パターンの範囲をバージョン別に指定する関数
         */
        private function _makeFixed():void {
            var __i:int;
            var __j:int;
            var __k:int;
            var __l:int;
            _fixed = new Array( _qrVersion * 4 + 17 );
            for ( __i = 0; __i < (_qrVersion * 4 + 17); __i++) {
                _fixed[__i] = new Array( _qrVersion * 4 + 17 );
            }
            switch( _qrVersion ) {
                case 1:
                        for ( __i = 0; __i < 8; __i++) {
                            for ( __j = 0; __j < 8; __j++) {
                                _fixed[__j][__i] = 
                                _fixed[__j][_qrVersion*4 + 9 + __i] = 
                                _fixed[_qrVersion*4 + 9 + __j][__i] = 1;
                            }
                        }
                        for (__i = 0; __i < 8; __i++) {
                            _fixed[8][__i] = 
                            _fixed[__i][8] = 
                            _fixed[_qrVersion * 4 + 9+__i][8] = 
                            _fixed[8][_qrVersion * 4 + 9+__i] = 1;
                        }
                        _fixed[8][8] = 1;
                        for ( __i = 9; __i < _qrVersion * 4 + 9; __i++ ) {
                            _fixed[6][__i] = _fixed[__i][6] = 1;
                        }
                    break;
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                        for ( __i = 0; __i < 8; __i++) {
                            for ( __j = 0; __j < 8; __j++) {
                                _fixed[__j][__i] = 
                                _fixed[__j][_qrVersion*4 + 9 + __i] = 
                                _fixed[_qrVersion*4 + 9 + __j][__i] = 1;
                            }
                        }
                        for (__i = 0; __i < 8; __i++) {
                            _fixed[8][__i] = 
                            _fixed[__i][8] = 
                            _fixed[_qrVersion * 4 + 9+__i][8] = 
                            _fixed[8][_qrVersion * 4 + 9+__i] = 1;
                        }
                        _fixed[8][8] = 1;
                        for ( __i = -2; __i <= 2; __i++ ) {
                            for ( __j = -2; __j <= 2; __j++ ) {
                                _fixed[_qrVersion * 4 + 10 + __j][_qrVersion * 4 + 10 + __i] = 1;
                            }
                        }
                        for ( __i = 9; __i < _qrVersion * 4 + 9; __i++ ) {
                            _fixed[6][__i] = _fixed[__i][6] = 1;
                        }
                    break;
                case 7:
                case 8:
                case 9:
                case 10:
                case 12:
                case 13:
                        for ( __i = 0; __i < 3; __i++) {
                            for ( __j = 0; __j < 6; __j++) {
                                _fixed[__j][_qrVersion*4 + 6 + __i] = 
                                _fixed[_qrVersion*4 + 6 + __i][__j] = 1;
                            }
                        }
                        for ( __i = 0; __i < 8; __i++) {
                            for ( __j = 0; __j < 8; __j++) {
                                _fixed[__j][__i] = 
                                _fixed[__j][_qrVersion*4 + 9 + __i] = 
                                _fixed[_qrVersion*4 + 9 + __j][__i] = 1;
                            }
                        }
                        for (__i = 0; __i < 8; __i++) {
                            _fixed[8][__i] = 
                            _fixed[__i][8] = 
                            _fixed[_qrVersion * 4 + 9+__i][8] = 
                            _fixed[8][_qrVersion * 4 + 9+__i] = 1;
                        }
                        _fixed[8][8] = 1;
                        
                        for( __k = 6; __k <= (_qrVersion*4 + 10); __k += (_qrVersion*2 + 2)){
                            for( __l = 6; __l <= (_qrVersion*4 + 10); __l += (_qrVersion*2 + 2)){
                                if(
                                    !((__k == 6) && (__l == (_qrVersion*4 + 10))) &&
                                    !((__l == 6) && (__k == (_qrVersion*4 + 10)))
                                ){ 
                                    for ( __i = -2; __i <= 2; __i++ ) {
                                        for ( __j = -2; __j <= 2; __j++ ) {
                                            _fixed[__k + __j][__l + __i] = 1;
                                        }
                                    }
                                }
                            } 
                        } 
                        for ( __i = 9; __i < _qrVersion * 4 + 9; __i++ ) {
                            _fixed[6][__i] = _fixed[__i][6] = 1;
                        }
                    break;
            }
        }
        /**
         * 座標(x,y)のビットパターンを返す関数
         */
        private function _getQR(x:uint, y:uint):uint {
            return _qr[y][x];
        }
        /**
         * 機能パターン情報を返す関数
         */
        private function _isFixed(x:uint, y:uint):uint {
            return _fixed[y][x];
        }
        /**
         * 形式情報をデコードする関数
         */
        private function _decode15_5():Array {
            var __str1:Array = new Array(15);
            var __str2:Array = new Array(15);
            var __i:uint;
            var __j:uint;
            var __S:Array = new Array(5); // シンドローム
            var __s:Array = new Array(3); // 誤り位置変数
            var __tempNum1:G4Num;
            var __tempNum2:G4Num;
            var __retArray:Array = new Array(5); // データ部
            var __checkPattern:Array = new Array(15); //マスク解除後の形式情報
            
            // シンドローム配列初期化
            for ( __j = 0; __j < 5; __j++ ) {
                __S[__j] = new G4Num(-1);
            }
            // 形式情報を取得
            for ( __i = 0; __i <= 5; __i++ ) {
                __str1[__i] = _getQR(8, __i);
            }
            __str1[6] = _getQR(8, 7);
            __str1[7] = _getQR(8, 8);
            __str1[8] = _getQR(7, 8);
            for ( __i = 0; __i <= 5; __i++ ) {
                __str1[__i + 9] = _getQR(5 - __i, 8);
            }
            for ( __i = 0; __i <= 7; __i++ ) {
                __str2[__i] = _getQR(_qrVersion * 4 + 16 - __i, 8);
            }
            for ( __i = 0; __i <= 6; __i++ ) {
                __str2[8+__i] = _getQR(8, _qrVersion * 4 + 10 + __i);
            }
            
            // マスク解除
            for ( __i = 0; __i < 15; __i++ ) {
                __checkPattern[__i] = __str1[14 - __i] ^ _xorPattern[__i];
            }
            
            for ( __i = 0; __i < 15; __i++ ) {
                if ( __checkPattern[__i] ) {
                    for ( __j = 0; __j < 5; __j+=2 ) {
                        __S[__j] = __S[__j].plus( new G4Num( __i * (__j + 1) ) );
                    }
                }
            }
            __S[1] = __S[0].multiply( __S[0] );
            __S[3] = __S[1].multiply( __S[1] );
            __s[0] = new G4Num( __S[0].getPower() );
            __tempNum1 = __S[4].plus( __S[1].multiply( __S[2] ) );
            __tempNum2 = __S[2].plus( __S[0].multiply( __S[1] ) );
            if ( (__tempNum1.getPower() < 0) || (__tempNum2.getPower() < 0) ) {
                __s[1] = new G4Num( -1 );
            } else {
                __s[1] = new G4Num( __tempNum1.getPower() - __tempNum2.getPower() + 15 );
            }
            __tempNum1 = __S[1].multiply( __s[0] );
            __tempNum2 = __S[0].multiply( __s[1] );
            __s[2] = __S[2].plus( __tempNum1.plus( __tempNum2 ) );
            
            for ( __i = 0; __i < 5; __i++ ) {
                __tempNum1 = new G4Num( (__i) * 3 );
                __tempNum2 = new G4Num( (__i) * 2 );
                __tempNum1 = __tempNum1.plus( __tempNum2.multiply( __s[0] ) );
                __tempNum2 = new G4Num( (__i) );
                __tempNum1 = __tempNum1.plus( __tempNum2.multiply( __s[1] ) );
                __tempNum1 = __tempNum1.plus( __s[2] );
                
                if ( __tempNum1.getPower() < 0 ) {
                    __retArray[__i] = __checkPattern[__i] ^ 1;
                } else {
                    __retArray[__i] = __checkPattern[__i];
                }
            }
            
            return __retArray;
        }
        
    }
}