あらすじ
この記事は Ruby Advent Calendar 2013 - Qiita [キータ] の 24 日目の記事です。
とりあえず、私用で URL から QR コードを生成したいので、 Ruby で実現できるか調べてみた。
成果物
とりあえず、以降の手順の QR コード作成方をもう少しゴチャゴチャやって Heroku にデプロイ。
課題
- 特にエラーチェックとかしてない
日本語がうまく読み取れない
今回使った rqrcode
の Issue の中にこんなものを発見した。 UTF8 strings under Ruby 1.9.2 · Issue #3 · whomwah/rqrcode · GitHub
で、やってみると、確かに日本語を QR コードに落とす事ができた!
ただし、ここでさらにわからないことが増えた…。
- UTF-8 文字列を安全に CP852 に変換する方法(今は
force_encoding
で無理やり変換している) - なんで CP852 なのか
- そもそも CP852 とは
参考サイト
- toretore/barby · GitHub
- Example Embed barcode - ThinReports - Matsukei Open Source Center
- Railsの画面にQRコードを表示 - 技術メモ的なモノと気になるモノ
- RubyでQRコードを作るには - まめ畑
- rubyでQRコード生成 - harry’s memorandum
環境
- Windows 7
- Ruby 1.9.3
- RubyGems 1.8.25
- Bundler 1.3.5
手順
barby
という Ruby のバーコード生成ライブラリを使用する- barby から QR コードを生成するために
rqrcode
が必要 - QR コードを画像で吐き出すために
chunky_png
が必要(画像なら何形式でもよかった) - 吐き出した png をブラウザから確認するために
sinatra
を使用
ソースコード
という事で、必要なgem。
gem 'sinatra'
gem 'barby'
gem 'rqrcode'
gem 'chunky_png'
URL を QR コードに変換するには、
- QR コードにしたい文字列を用意
- QR コードとして読み込む
- 変換したい形式の Outputter で読み込む(今回は png )
- 読み込んだ バイナリデータ を書き出す
コードはこんな感じ。これは google の Url を QR に変換している。
# encoding: utf-8
require "barby"
require "barby/barcode/qr_code"
require "barby/outputter/ascii_outputter"
require "barby/outputter/png_outputter"
require "rqrcode"
module QR
extend self
def barcode(type, data=nil)
if data.nil? then
data = <<-"EOS"
http://google.com
EOS
end
code = Barby::QrCode.new(data.encode("UTF-8"))
case type
when :png
blob = Barby::PngOutputter.new(code)
File.open('./barcode.png', 'wb') do |f|
png = blob.to_png
f.write png
end
when :ascii
code.to_ascii
end
end
end
if $0 == __FILE__ then
puts QR::barcode(:ascii)
end
一番初めは ASCII で出力してみるといいかも。
出した結果。
$ ruby qr.rb
X X X X X X X X X X X X X X X X X X
X X X X X X X X X
X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X
X X X X X X X X X
X X X X X X X X X X X X X X X X X X X
X X X X X
X X X X X X X X X X X X X
X X X X X X X X X X
X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X
X X X X X X X X X X X X X X X X
X X X X X X X X X
X X X X X X X X X X X X
X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X
X X X X X X X
X X X X X X X X X X X X X X X X
X X X X X X
X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X
X X X X X X X X X X X X X
X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X
ここに sinatra ( start.rb
)から呼ぶように。
equire 'sinatra'
require 'qr'
get '/' do
code = QR::barcode(:png)
'<img src="barcode.png">'
end
はまったとこ
バイナリファイルを書き込む時は b を忘れないようにする!
画像ファイルは生成されるんだけど、開いてみると「こわれています」と表示されてしまう……。
処理の途中でバイナリを確認していくと、こうなっていた。
正常な場合のバイナリデータ
ソース内で file オープンして write する直前のものを確認
89 50 4E 47 0D 0A 1A 0A ...
「こわれている」画像のバイナリデータ
実際に生成されたブツをバイナリエディタで確認
89 50 4E 47 0D 0D 0A 1A 0D 0A ...
ん?なんか違う。
シグネチャは PNG ファイルであることを確認するために使用されます。 シグネチャは必ず以下の8バイトとなっています。
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a
なるほど。シグネチャからしておかしい。そもそもはじめから PNG になっていないのか。
なんでだろう?
…と、よくよくコードを見直してみると、 File.open
した時のオプションが w
だった。
File.open('./barcode.png', 'w') do |f|
b
オプションを付加すると正常な画像になった!
File.open('./barcode.png', 'wb') do |f|
バイナリで書き込むの初めてだから失念していた。注意しないといかん。