読者です 読者をやめる 読者になる 読者になる

モバイルFlexでのQRコードリーダーの作成方法


QRコードリーダーの作成をやってみました。
さすがにリアルタイムでの処理という訳にはいきませんが、比較的軽い動作で認識します。
まず、zxingが必要なのでダウンロードします。
ダウンロードして解凍したら、「xing/actionscript/core/src/com」のcomフォルダをFlexのプロジェクトsrcにコピーします。
実行時にライブラリでのエラーが出ますが、適度にコメントアウトすれば問題ありません。

DecoderResult.as
//import mx.controls.List;
BufferedImageLuminanceSource.mxml
//import mx.controls.Image;

ソースはこちら

<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
        xmlns:s="library://ns.adobe.com/flex/spark" title="QRCodeReader">
    <fx:Script>
        <![CDATA[
            import com.google.zxing.BarcodeFormat;
            import com.google.zxing.BinaryBitmap;
            import com.google.zxing.BufferedImageLuminanceSource;
            import com.google.zxing.DecodeHintType;
            import com.google.zxing.Result;
            import com.google.zxing.client.result.ParsedResult;
            import com.google.zxing.client.result.ResultParser;
            import com.google.zxing.common.GlobalHistogramBinarizer;
            import com.google.zxing.common.flexdatatypes.HashTable;
            import com.google.zxing.qrcode.QRCodeReader;
            import spark.components.VideoDisplay;
            private var camera:Camera;
            private var videoDisplay:Video = new Video();
            private var qrReader:QRCodeReader;
            private var cameraStarted:Boolean = false;
            //ボタンクリックイベント
            protected function btn_clickHandler(event:MouseEvent):void
            {
                //ボタンのラベル名によって実行する関数を分ける
                if( ( event.target as Button ).label == "Start Camera" ){
                    setCamera();
                }else{
                    decodeSnapshot();
                }
            }
            //カメラ設定とステージへ追加
            protected function setCamera():void
            {
                if (Camera.isSupported)
                {
                    camera=Camera.getCamera();
                    camera.setMode(640, 480, 24);
                    videoDisplay.x = 360;
                    videoDisplay.y = 40;
                    sv.addChild(videoDisplay);
                    videoDisplay.attachCamera(camera);
                    videoDisplay.rotation=90;
                    qrReader=new QRCodeReader();
                    btn.label = "Scan Now";
                    lbl.text = "";
                    cameraStarted = true;
                }
                else {
                    lbl.text = "no camera found";
                }
            }
            //カメラ画像のスナップショット
            private var bmd:BitmapData;
            public function decodeSnapshot():void
            {
                lbl.text="checking...";
                bmd=new BitmapData(640, 480);
                bmd.draw(videoDisplay, null, null, null, null, true);
                videoDisplay.cacheAsBitmap=true;
                videoDisplay.cacheAsBitmapMatrix=new Matrix;
                decodeBitmapData(bmd, 640, 480);
                bmd.dispose();
                bmd=null;
                System.gc();
            }
            //送られて画像からデコード
            public function decodeBitmapData(bmpd:BitmapData, width:int, height:int):void
            {
                var lsource:BufferedImageLuminanceSource=new BufferedImageLuminanceSource(bmpd);
                var bitmap:BinaryBitmap=new BinaryBitmap(new GlobalHistogramBinarizer(lsource));
                var ht:HashTable=null;
                ht=this.getAllHints();
                var res:Result=null;
                try {
                    res=qrReader.decode(bitmap, ht);
                }
                catch (event:Error) {
                }
                if (res == null) {
                    videoDisplay.clear();
                    lbl.text="nothing decoded";
                }
                else {
                    var parsedResult:ParsedResult=ResultParser.parseResult(res);
                    lbl.text=parsedResult.getDisplayResult();
                    sv.removeChild(videoDisplay);
                    cameraStarted = false;
                    btn.label = "Start Camera";
                }
            }
            public function getAllHints():HashTable
            {
                var ht:HashTable=new HashTable;
                ht.Add(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);
                return ht;
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
    </fx:Declarations>
    <s:VGroup width="100%" horizontalAlign="center" id="vg">
        <s:SpriteVisualElement id="sv" width="480" height="480"/>
        <s:Label id="lbl" text="" />
        <s:Button id="btn" label="Start Camera" width="220" height="93" click="btn_clickHandler(event)"/>
    </s:VGroup>
</s:View>

参考リンク

How do I add a QR code reader to my Flex mobile application?
どうやってモバイルでQRコード認識するの?ほとんどこのソースを使っております。
zxing
ActionScript用のコード認識ライブラリがあります