RubyでQRコードを作るには
唐突ですが、RubyでQRコードを吐き出したいと思いライブラリを探していたらもちろんあったのですが、若干挙動に不安が。
というわけで諸々メモ。
今回はWindows上のRuby1.8.6で行っています。(いい加減バージョン上げなければ)
Ruby qrcodeでググルと一番最初にQRコードクラスライブラリ for Ruby - QRcode encode class library for Rubyがヒットしますが、こちらはPHP版からの移植で、かつRuby/GDが必要とされておりWindows上でRuby/GDを使うには若干面倒。参考→無理やりWindowsでruby/gd - Ryoの開発日記
なので、探していたらありました。
gemで入れられます。
rqrというライブラリです。
公式サイトはrqr
PS・JPEG・PNG・EPS・TIFF形式で出力出来ます。
リリースエントリを参照すると
サイテック社にてフリーソフトとして配布されているC++のコアをANSIに対応し、rubyでラッピングしました。
pools.jp | rubyでQRCodeを作成するライブラリrqrをリリース
extを使っているため比較的高速に動作しますし、ひと通りの画像形式で出力できるという特徴を持っています。
と書いてあります。
Windows用のパッケージを開くと、QR.soが入っています。
インストールは簡単で
gem install rqr
で完了です。
もしくは、http://rubyforge.org/frs/?group_id=6324:title:bokmarkからWindows用のパッケージをDLして
gem install rqr --local
でも可能です。
Linuxでは
yum install libjpeg yum install libpng yum install libtiff
が必要です。
Portを使ったインストール方法などは公式ページにまとまっています。
ちなみに、Ubuntuでは
sudo apt-get install libjpeg-dev sudo apt-get install libpng12-dev sudo apt-get install libtiff-dev
です。
しかし、ここで問題が。
インストール中に
No definition for _wrap_CQR_Encode_m_nSymbleSize_set
No definition for _wrap_CQR_Encode_EncodeData
の様なエラーが続々と出ます。
しかし、インストールは成功し正常に動作します・・・。
createメソッドが取るオプションは
# QRCode options (passed to RQR::QRCode.new())
# Use options with hash values.
# :level L:0, M:1(default), Q:2, H:3
# :version S:0(default), M:1, L:2
# :auto_extent true|false auto extent if over version size
# :masking masking pattern 0-7, -1(default auto)
# :length data length
# :module_size module size (pixel)
# :eps_preview true|false
ですが、levelとversionが良くわからなかったのですが、バージョンはQRコードのサイズでレベルが高いほど情報をつめられる
levelはエラー訂正レベルで
レベルL 約 7%
レベルM 約 15%
レベルQ 約 25%
レベルH 約 30%
のエラー訂正が可能ですが、訂正レベルが高くなるほど追加の情報量が多くなります。
QRコードの詳しい事はQRコードドットコム|QRコードのバージョン|株式会社デンソーウェーブにまとまっています。
使い方は非常に簡単です。
公式サイトに書かれている通りです。
日本語も入力可能で改行ももちろん大丈夫です。
文字コードはSJISにしないと日本語は化けてしまい読み取れません。
もちろん、日本語のファイル名も可能です。
ファイル形式は拡張子から判断しますが、第3引数にシンボルを渡す事でも指定可能です。
require 'rubygems' require 'rqr' $KCODE = "SJIS" RQR::QRCode.create do |qr| qr.save("サイト\r\nhttp://mame-lab.com/", "hoge.png") end
しかし、素直に作成されるわけではないです。
エラーが表示されます(画像は出力されますが)
c:/ruby/lib/ruby/gems/1.8/gems/rqr-0.2.2-x86-mswin32/lib/rqr/qrcode.rb:57:in `close': undefined method `close' for #<QR::QRDrawPNG:0x2d976f8> (NoMethodError)
closeメソッドない。
つまり、ストリーム閉じてないのか?
と思いソースを見ると。
該当箇所
def close() @encoder = nil if @encoder p @imager.respond_to? :close, true #false <=追加して確認 (@imager.close; @imager = nil) if @imager #ここ end
@imagerにcloseメソッドない模様。
しかし、これは
def save_as_png(path) @imager=QR::QRDrawPNG.new @imager.draw(path, @options[:module_size], @encoder.m_nSymbleSize, @encoder.m_byModuleData, nil) end
各画像形式用のインスタンスを保持しています。
ここからはC++のソースを見ると
int QRDrawPNG::write() { //画像書き出し用の処理 fclose(stream); //←閉じてる return(0); #else return(1); #endif }
書き出しの段階でストリームを閉じているので問題は無いけれど、close関数ないのでメソッドないっすってエラーが出ている模様。
エラーは出ても画像は正常に書き出せているので、気になる場合は該当の箇所の判定を@imagerがnilかどうかではなく、closeメソッドがあるかどうかを判定したほうがいいかも。
ちなみにLinuxではcloseのエラーは出ないようです。
何か勘違いしてるかな?
指摘などありましたらコメントお願いします。