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

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

forked from: QR Code sample from http://www.libspark.org/svn/as3/QRCodeReader/trunk/sample/ReadQrCodeSample.as

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
*
/**
 * Copyright snipsnipsnip ( http://wonderfl.net/user/snipsnipsnip )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/v0LN
 */

// forked from RobotHacker's QR Code sample from http://www.libspark.org/svn/as3/QRCodeReader/trunk/sample/ReadQrCodeSample.as
/**************************************************************************
* 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 
{
	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;
	/**
	 * QRコード解析クラスの使用例です
	 * @author Kenichi UENO
	 */
	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 = "Click here to start!";
			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;
		}
		
	}
}