ログイン TOPに戻る
PHPでQRコード作成と言えば
http://www.swetake.com/qr/qr_cgi.html
が超有名なんだけど、

今回は趣向を変えて、
libqrencode版
http://megaui.net/fukuchi/works/qrencode/index.html
を作って見ました。

サンプルはこちら

■メリット
車輪の再発明ではあるんですが、、、

・libqrencodeというCで出来た軽量のライブラリを使用する。
・GDがいらない。(画像を作らなければ)
・漢字モードが使える

などがメリットです。


■使い方。
例によって、pecl-codegenを使ってPHP拡張を作りました。

まずは、ともかく
libqrencodeをインストール。
http://megaui.net/fukuchi/works/qrencode/index.html

./configure
make
make install

そして、
qrencode-0.0.1.tar.gz
php-qrencode-0.0.2.tar.gz
(ちょい修正、20070409)
をダウンロードして

tar xvfz qrencode-0.0.2.tar.gz
cd qrencode-0.0.2
phpize
./configure
make
make install

あとは、php.iniに

extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20060613/"
extension=qrencode.so

などとして下さい。


これで、qrencode()という関数が使えるようになります。

使い方は、

<?
$str = "ABCDEFG";
$qrdata = qrencode($str,3,QR_ECLEVEL_M,QR_MODE_8);
?>
<html>
<head>
<style>
.qr_line{
    clear:both;
    overflow:hidden;
    height:4px;
}
.qr_line b{
    background:#fff;
    width:4px;
    height:4px;
    float:left;
    overflow:hidden;
}
.qr_line i{
    background:#000;
    width:4px;
    height:4px;
    float:left;
    overflow:hidden;
}
</style>
</head>
<body>
<?foreach($qrdata as $row){?>
<div class="qr_line">
<?foreach($row as $cell){?>
<?=($cell=="0")?"<b></b>":"<i></i>"?>
<?}?>
</div>
<?}?>
?>

こんな感じ。
$qrdataに、1や0が沢山はいった二次元配列が帰ってきますので、
画像にするなり、テーブルを作るなり、CSSで書くなり、
好きにして下さいませ。
1が黒いところ、0が白いところです。

qrencode関数は、
$ret = qrencode(文字列,バージョン,誤り訂正レベル,モード);
となってます。

引数は、

1.QRコードに入れたい文字列
2.バージョン、QRコードのサイズです。大きくするとドットが4つづつ増えます。
 小さくしても、文字があふれると自動で大きくなるようです。
3.誤り訂正レベル4段階
    QR_ECLEVEL_L  復元能力7%
    QR_ECLEVEL_M  復元能力15%
    QR_ECLEVEL_Q  復元能力25%
    QR_ECLEVEL_H  復元能力30%
  復元能力が高くなると入れれる文字列が減ります。
4.モード
    QR_MODE_NUM   数字モード
    QR_MODE_AN    英数字モード
    QR_MODE_8     バイナリモード
    QR_MODE_KANJI SJIS漢字モード

です。

以上、うまく動いたら是非教えてくださいませ!!

最近マイブームのcodegenで今度はPHPからCannaを使う拡張を作って見た。

WEBサービスも作った。
http://www.netflowers.co.jp/canna/

すげー。
本当は変換の候補とか出さないと行け無かったりするので、
まぁ、実用性は無いんだけど、、個人的にはちょっと感動。



せっかくなので、ソースは公開。
C言語良くわからないので、これで良いのかさっぱり不明。
わかる方添削してくれると超嬉しいです。

canna-0.0.1.tar.gz

使い方は、

当然ですが、cannaが必要。

yum install Canna
yum install Canna-libs
yum install Canna-devel

あとは、いつもどおり、

tar xvfz canna-0.0.1.tar.gz
cd canna-0.0.1
phpize
./configure
make
make install

php.iniに

extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20060613/"
extension=canna.so

ってすると、

$ret =  kanji_string("honzitu ha seiten nari.");

で、$retに配列で帰ってくる。
array(1) { [0]=> string(16) "本日は青天なり。" }

なんで配列かって言うと、\nで区切って有った場合に分けるため。

で、文字コードはeucで帰ってくるので必要な場合は、mb_convert_encodingなりして下さい。

うまく動いたかた、教えてくれると嬉しいです。

codegenの
canna.xmlは下記の通り

<?xml version="1.0" ?>
<extension name="canna" version="1.0.0">
 <deps language="c" platform="all">
  <with defaults="/usr:/usr/local" testfile="include/canna/jrkanji.h">
   <header name="canna/jrkanji.h" />
   <lib name="canna" platform="all" />
  </with>
 </deps>
 <function name="kanji_string">
  <proto>array kanji_string(string src)</proto>
  <code>
    <![CDATA[

    int c, nbytes ,i,len;
    unsigned char workbuf[1024];
    jrKanjiStatus ks;

   

    jrKanjiControl(0, KC_INITIALIZE, 0);
    {
      jrKanjiStatusWithValue ksv;

      ksv.ks = &ks;
      ksv.buffer = workbuf;
      ksv.bytes_buffer = 1024;
      ksv.val = CANNA_MODE_HenkanMode;
      jrKanjiControl(0, KC_CHANGEMODE, &ksv);
    }
    len = (int) strlen(src);
    array_init(return_value);
   
    for (i=0;i<len;i++) {
      nbytes = jrKanjiString(0, (int)src[i], workbuf, 1024, &ks);
      if (nbytes > 0) {
        workbuf[nbytes] = '\0';
        add_next_index_stringl(return_value, workbuf,nbytes,1);
      }
    }

    if(src[len-1] != '\n'){
      nbytes = jrKanjiString(0, '\n', workbuf, 1024, &ks);
      if (nbytes > 0) {
        workbuf[nbytes] = '\0';
        add_next_index_stringl(return_value, workbuf,nbytes,1);
      }
    }

    jrKanjiControl(0, KC_FINALIZE, 0);
   

    ]]>
  </code>
 </function>

</extension>


また、Perlばっかりずるいので、
PHP版も作って見た。

decodeqr-0.0.1.tar.gz


WEBサービスもやってみた。
http://www.netflowers.co.jp/decodeqr/

使い方は、
まず、

OenCVとlibdecoderqrをインストール
http://sourceforge.net/projects/opencvlibrary/

http://trac.koka-in.org/libdecodeqr

decoderqrをダウンロードして、
解凍

tar zvfz decodeqr-0.0.1.tar.gz
cd decodeqr-0.0.1
phpize
./configure
make
make install

で、php.iniに

extension_dir = "/usr/local/lib/php/extensions/no-debug-non-zts-20060613/"
extension=decodeqr.so

ってすると、

$str = decodeqr(ファイル名);

で、デコードした内容がかえって来るようになる。
だめな場合はfalseが帰ってきます。

認識率がかなりだめみたいで、うまく認識できるQRコードを探す方が難しいです。。。。。
まぁ、ねたと言うことで、、、、

codegenも公開。
生まれて二回目のcodegenです。間違ってたらごめん。

decodeqr.xml

<?xml version="1.0" ?>
<extension name="decodeqr" version="1.0.0">
 <deps language="c" platform="all">
  <with defaults="/usr:/usr/local" testfile="include/decodeqr.h">
   <header name="opencv/cv.h" />
   <header name="opencv/highgui.h" />
   <header name="decodeqr.h" />

   <lib name="decodeqr" platform="all" />
   <lib name="cv" platform="all" />
   <lib name="cvaux" platform="all" />
   <lib name="highgui" platform="all" />
   <lib name="cxcore" platform="all" />
   <lib name="ml" platform="all" />

  </with>
 </deps>
 <function name="decodeqr">
  <proto>array decodeqr(string filename)</proto>
  <code>
    <![CDATA[

    IplImage *image;
    QrDecoderHandle decoder;
    QrCodeHeader header;
    char *buf;

    image = cvLoadImage(filename, 1);
    if (!image) {
      RETURN_FALSE;
    }
    decoder = qr_decoder_open();

    (void) qr_decoder_decode_image(decoder, image,
            DEFAULT_ADAPTIVE_TH_SIZE, DEFAULT_ADAPTIVE_TH_DELTA);

    if (qr_decoder_get_header(decoder, &header)) {
        buf = emalloc(header.byte_size + 1);
        qr_decoder_get_body(decoder, (unsigned char *)buf, header.byte_size + 1);
        RETURN_STRING(buf, 1);
        efree(buf);
    } else {
        RETURN_FALSE;
    }
    qr_decoder_close(decoder);
    cvReleaseImage(&image);
   

    ]]>
  </code>
 </function>

</extension>





PHPの拡張は初めて作ったんだけど、
codegenというのを使うと結構簡単に出来る。

以下、顔検出プラグインを作るまで。

codegenをインストールする。
# pear install -a codegen_pecl

以下のxmlファイルを、face_detect.xmlとして保存。

<?xml version="1.0" ?>
<extension name="face_detect" version="0.0.1">
<deps language="c" platform="all">
<with defaults="/usr:/usr/local" testfile="include/opencv/cv.h">
<header name="opencv/cv.h" />
<header name="opencv/highgui.h" />

<lib name="cv" platform="all" />
<lib name="cvaux" platform="all" />
<lib name="highgui" platform="all" />
<lib name="cxcore" platform="all" />
<lib name="ml" platform="all" />

</with>
</deps>
<function name="face_detect">
<proto>array face_detect(string filename,string cascade_name)</proto>
<code>
<![CDATA[

int i;
CvHaarClassifierCascade* cascade = 0;
IplImage *img, *gray;
CvMemStorage *storage;
CvSeq *objects;
CvRect *rect;


cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0 );
if( !cascade ){
RETURN_FALSE;
}

img = cvLoadImage(filename,1);
if( !img ){
RETURN_FALSE;
}

gray = cvCreateImage(cvSize(img->width, img->height), 8, 1);
cvCvtColor(img, gray, CV_BGR2GRAY);
cvEqualizeHist(gray, gray);

storage = cvCreateMemStorage(0);

objects = cvHaarDetectObjects(gray, cascade, storage,
1.1, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(0, 0));

array_init(return_value);


for (i = 0; i < (objects ? objects->total : 0); i++) {
rect = (CvRect *) cvGetSeqElem(objects, i);

zval *new_array;
MAKE_STD_ZVAL(new_array);
array_init(new_array);

add_assoc_long(new_array,"x",rect->x);
add_assoc_long(new_array,"y",rect->y);
add_assoc_long(new_array,"width",rect->width);
add_assoc_long(new_array,"height",rect->height);

add_next_index_zval(return_value, new_array);
}

cvReleaseMemStorage(&storage);
cvReleaseImage(&img);
cvReleaseImage(&gray);

]]>
</code>
</function>

</extension>

pecl-gen -f face_detect.xml
cd face_detect
phpize
./configure
make
make install

以上。簡単でしょ?

使い方は、
<?

$picture = "picture.jpg";
$cascade = "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt.xml";

//顔の位置を検出
$faces = face_detect($picture ,$cascade);

?>


※ソースの中身は、これで良いのか悪いのか、激しく不明。
特にCの部分とか、ライブラリの読み込みとか。
誰か、エロイ人教えて。