2019-03-31

JavaScriptでQR Codeのencode / decodeと、これを試してJavaScriptの画像周りで気づいたこと

Ruby で QR Code を作るのは以前からやってるんだけど、

これを JavaScript でやってみたらどうなるか実験。

特に scanner 部分を独自アプリで作り込むと独自ルールを仕込むことができて便利1なので、生成された QR コードのチェックを目視に頼り切る必要がなくなるし、scanner を UI と融合させやすいのが JavaScript の強み。

気づいたこと

encodeは「見える」が最優先で画像化は後回し

Ruby の場合は

  1. QR Code のパターンを生成
  2. これを内部で保持しつつどのフォーマットで出力するか

を考えるだけでよかった。上の rqrcode_png_bin で言うと、もともとは rqrcode がパターンを保持し、rqrcode_png が rqrcode と chunky_png をミックスして PNG 出力できるもので、rqrcode_png_bin はそれに CLI のガワを被せただけのものだ。

ところが JavaScript の場合はそもそもブラウザ上でならそのまま見える状態にすぐ持っていけるので、それを目指す場合が多い。具体的には HTML タグだったり Canvas 要素だったり。

ところが HTML タグも Canvas 要素も Node.js 環境ではそのままで使えない。少なくとも「画像ファイル」としてそのまま取り出すことはできない。UI と融合させてブラウザで一つ一つ手作りする分にはこれでよいが、画像として取り出してデータとして活用したい場合にはもう一工夫必要になるし、同じ生成処理を使って一括生成したい場合にもこのままでは使えない。

具体的には流れとしては以下のようになるようだ。

  1. dataURL にする
  2. dataURL を Buffer に変換する
  3. Buffer をファイルに出力する

ブラウザであれば 1 の dataURL を img 要素に与えればおしまい。画像ファイル化も、右クリックして保存すればおしまいである。Node.js であれば 2 以降を実装することで自動的に画像ファイルを生成することができる。

※ ただしこの際、画像の縦横のサイズが指定通りにぴったり同じになるかどうかは実装による。そもそも QR コードはピクセルでなく「モジュール」が基本単位であり、ピクセルは基本単位ではない。QR コードのパターンをそのまま dataURL に変換した img を生成した場合、基本的には指定サイズより小さいものができあがる。Canvas 上に描く場合は Canvas 側で先に指定サイズにしたがって要素ができあがり、その上に描画するので大きさが足りない場合は単に余白が大きくなる。

画像の取り込みはArrayBufferを作るところから

  • 画像フォーマットに左右されずにピクセル情報を取り扱うには Canvas の ImageData を利用する
  • ImageData.data は ArrayBuffer なので
  • Scanner は ArrayBuffer を解釈すれば ok

実際、以下のライブラリは第1引数に imageData と書かれているが、これは ImagaData() そのものではなく ArrayBuffer を受け取る。

cozmo/jsQR: A pure javascript QR code reading library. This library takes in raw images and will locate, extract and parse any QR code found within.

これを前提にすると、ついでに FileReader API も .readAsArrayBuffer() を使えば ArrayBuffer を返すので、

Camera -> getUserMedia() -> Canvas Context -> ImageData  -> ArrayBuffer
       -> input type="file"                -> FileReader -> ArrayBuffer

の両方のルートでカメラから ArrayBuffer を経由して QR コードリーダーを実装できることが分かった。

カメラ画像の取り込みはデバイスとブラウザの特性によって選び分けた方がよさそうという話もあるけど、そこはまた今度。

※ ちなみに昨日の https サーバの話はこの video 要素の取り回しがきっかけ。

cf.

使うとよさげなライブラリ

Accelerated Shape Detection in Images によると WICG で扱ってて Barcode Detection も standard な機能になりそうなんすね…。

  1. 例えばNGワードとか 

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm