2007年03月19日 02:00 [Edit]

java + perl - QRCodeを読み取るCGI

こちらにインスパイヤされて作りました。

spiritlooseのはてなダイアリー - QRコードデコードライブラリlibdecodeqrを使ってみた
デコードライブラリはいままでなかったような。

Demo:

URI of QRCode Image:
Text:

ただし、インスパイヤとあるのは、今回はlibdecodeqrではなく、こちらを採用したから。

Preface

spiritlooseのはてなダイアリー - QRコードデコードライブラリlibdecodeqrを使ってみた
あれ。。。認識力が・・・
俺の環境かしら。サンプルの画像もほとんど認識しない。

認識率の点で、こちらの方が上だったので。Javaってところがあれですが。

はっきり言って重いです。認識に1秒ぐらいかかります。そんなわけなので、あくまで本entryの例はサンプルということで。間違っても私の鯖を前提としたWebサービスをこさえたりしないでね。その代わりRecipeを以下に書いておくので。

Recipe

  1. qrcode 0.7.2を使えるようにしておく
    1. JDKを使えるようにしておく 当然ですが、JDKがまだない場合はJDKをインストールしておきます。私の鯖はFreeBSDなので、
      pkg_add -vr jdk15
      としました。
    2. Sourceforgeからソースを取ってきたら、以下のとおり。
      % unzip qrcode.zip
      % cd qrcode/example
      % javac -cp ../lib/qrcode.jar QRCodeDecoderCUIExample.java
      
    3. 以下が正常に実行されればOK
      % java -cp .:../lib/qrcode.jar QRCodeDecoderCUIExample ../res/qrcode.jpg
      
  2. ラッパースクリプトを用意する

    生classはひじょ〜に使いづらいので、ラッパーを用意します。ソースはこんな。

    qrdecode
    #!/usr/local/bin/perl
    use strict;
    use warnings;
    use Cwd qw/abs_path/;
    my $file = shift or die;
    my $path = abs_path($file);
    chdir "./qrcode/example";
    my $java = "/usr/local/bin/java";
    exec $java, qw(-cp .:../lib/qrcode.jar QRCodeDecoderCUIExample), $path;
    

    qrdecode imagefileで読み取った結果を標準出力します。

  3. CGIを用意する

    ここではJSONPを返すようにしてあります。ソースはこんな。

    qrdecode.cgi
    #!/usr/local/bin/perl
    use strict;
    use warnings;
    use LWP::UserAgent;
    use CGI::Carp qw/fatalsToBrowser/;
    use Encode;
    use Encode::Guess;
    use JSON::Syck;
    
    my $timeout    = 15;              # seconds;
    my $max_size   = 1024 * 1024;     # bytes;
    
    my $uri = $ENV{PATH_INFO};
    die "No callback" unless $uri =~ s,^/([^/]+)/,,o; 
    my $callback = $1;
    $uri =~ m,http://,o or die "$uri invalid";
    $uri .= '?' . $ENV{QUERY_STRING} if $ENV{QUERY_STRING};
    
    my $tmpfile = "./tmp/$$";        
    my $ua = LWP::UserAgent->new(
                                 timeout  => $timeout,
                                 max_size => $max_size,
                                );
    my $res = $ua->get($uri, ':content_file'  => $tmpfile);
    die $res->status_line unless $res->is_success;
    
    open my $efh, '-|' or exec "./qrdecode $tmpfile 2>&1";
    my $bytes = do{ local $/; <$efh> };
    close $efh;
    unlink $tmpfile;
    
    my $enc = guess_encoding($bytes, qw/cp932 eucjp/);
    $enc = find_encoding('ascii') unless ref $enc;
    my $str = $enc->decode($bytes);
    
    # binmode STDOUT, ":utf8";
    print
        "Content-Type: application/x-javascript; charset=utf-8\n\n",
        $callback, '(', JSON::Syck::Dump(\$str), ");\n";
    

    見ての通り、先ほどのラッパースクリプトをexecしてます。パフォーマンス的にもセキュリティー的にもプロダクションレベルとは言い難いのですが、これで一応オンラインQRコードデコーダーの一丁あがりです。

Enjoy!

Dan the QR Decoder


この記事へのトラックバックURL

この記事へのトラックバック
<p>今回は開発者のために、先日リリースした「<a href="http://yois.jp/" target="_blank">ソーシャルQRコードブックマーク - よいさいと(β)</a>」の裏側のお話を書いておきます。 </p> <p>このエントリは、<a href="http://www.rubyonrails.org/" target="_blank">Ruby ...
Ruby on Railsで携帯からファイルのアップロード(+送信者認証)【koress.jp】at 2007年09月29日 23:36
この記事へのコメント
むー。OpenCVじゃ無いんだ。(CGI起動して)(必要ならクラスパスを通して)Javaをexecしてでは何でも出来るじゃないか。違う、そうじゃないんだ。Perlでやってほしいんだ。(< 勝手な野次馬)
・・・と言うのは、リンク元でやっておられるんですね。

サービスにするなら、やっぱりTomcatたてるとかになるんでしょうかね。
Posted by 野次馬 at 2007年03月19日 02:28