はじめに
面白いものを見つけました。コマンドラインでQRコードを表示できるものです。これまではずっと:
コマンドラインでsyncサービスを起動
エディタでコードを書き、ブラウザで確認
...ある程度書けたら
ブラウザのプラグインでQRコードを生成
スマホを100台取り出してスキャンしてテスト
...あれ、問題がある
修正してもうまくいかない。シーンが複雑なので、切り出して原因を特定する必要がある
テスト用ファイルをコピー
再度QRコードを生成し、スキャンしてテスト。よし完了
...おっと、また別の問題が見つかった
...
ブラウザのQRコードプラグインで要件はほぼ満たせますが、IDE、ブラウザ、ターミナル、Finderの間を頻繁に行き来するのは少し面倒です。しかし、より良い方法が見つからず……。コマンドラインQRコードを見るまでは。なんて賢いんでしょう。
1. 原理
「コマンドラインQRコード」と聞いて、原理は想像がつきます。画面に出力する際に、前景色、背景色、テキストスタイルを制御できることを利用しています。
QRコードを出力するには、背景色を変更できれば十分です。白いスペースと黒いスペースを組み合わせることで作ることができます。
例えば:
# focus here と出力
# focus は黒背景に白文字、スペースはデフォルト、here は青背景に白文字で太字
echo "\e[40;0;37mfocus\e[0m \e[44;1;37mhere\e[0m"
\e[0m はデフォルトスタイルにリセットします。一般的な制御シーケンスの形式は:
# \e[ で始まり、m で終わる
# セミコロンで区切られた3つの値は、それぞれ背景色、テキストスタイル、前景色
\e[40;0;37m
サポートされている値は以下の通りです:
# テキストスタイル
0: 標準テキスト
1: 太字
4: 下線
# 前景色 30-37
30: 黒
31: 赤
32: 緑
33: 黄
34: 青
35: 紫
36: シアン
37: 白
# 背景色 40-47
40: 黒
41: 赤
42: 緑
43: 黄
44: 青
45: 紫
46: シアン
47: 白
さらにより強力なものもあり、カーソルの移動、特定の行の削除、画面のクリアなどがあります。例えば、文字によるプログレスインジケーター:
echo -n '-'
arr=('\\' '|' '/' '-' '|' '100%')
for c in ${arr[@]};
do
# 1秒待機
sleep 1
# 左に1つ戻り、文字を出力
echo -en "\033[1D$c"
done
2. 具体的な実装
1. QRコードメタデータの生成
入力された文字列に基づき、QRコードの規則に従って2値行列を計算します。
このプロセスを自力で実装するのはかなり骨が折れます。なぜならQRコードは数百もの特許を持つ技術だからです。詳細は http://www.qrcode.com/jp/patent.html を参照。ISO Specification を購入(または入手)して実装する必要があります:
Obtaining QR Code Specification
QR Code is established as an ISO (ISO/IEC18004) standard. QR Code specification can, therefore, be purchased from this organization.
Purchasing ISO Standards
Please search by inputting ISO No.18004 or X0510 to "Search and ISO Catalogue". http://www.iso.ch/iso/en/prods-services/ISOstore/store.html
しかし、オープンソース版があり、様々な言語で実装されています:https://github.com/kazuhikoarase/qrcode-generator
それでも、いくつかの概念を知っておく必要があります:
-
サイズ(仕様書では
Version、上記のオープンソース実装ではTypeNumberと呼ばれます)値は
1から40で、1は最小の21x21行列、40は最大の177x177に対応します。 -
位置検出パターン(ファインダパターン)
最も目立つのは、QRコードの四隅のうち3つにある回し車のような四角い枠です。3つの点で1つの矩形を確定します。他の場所にも位置決めのためのパターンがあります。
-
誤り訂正レベル
'L', 'M', 'Q', 'H'の4つのレベルがあります。レベルが高いほど、より多くの汚れや欠損に耐えられますが、その分誤り訂正データが増えます。これにより、デザイン性の高いQRコードなども可能になります。 -
データタイプ
予約データ(形式情報、バージョン情報、位置検出パターン情報)、実際のデータ情報、および誤り訂正データ。
2. 出力
前述の qrcode-generator の主な JS API は以下の通りです:
// インスタンス作成
qrcode(typeNumber, errorCorrectionLevel) => QRCode
// エンコードする文字列を渡す
addData(data, mode) => void
// 行列を計算
make() => void
// 結果行列の行列数(列数=行数)を取得
getModuleCount() => number
// 行列のセルの値を取得
isDark(row, col) => boolean
メタデータができたら、行列をトラバースして黒白のスペース文字列を連結し、出力します:
// 黒白のスペース
var black = "\033[40m \033[0m",
white = "\033[47m \033[0m",
toCell = function (isBlack) {
return isBlack ? black : white;
},
repeat = function (color) {
return {
times: function (count) {
return new Array(count).join(color);
}
};
},
fill = function(length, value) {
var arr = new Array(length);
for (var i = 0; i < length; i++) {
arr[i] = value;
}
return arr;
};
//...インスタンス作成と行列計算部分は省略
// トラバース
var border = repeat(white).times(qrcode.getModuleCount() + 3);
output += border + '\n';
qrcode.modules.forEach(function (row) {
output += white;
output += row.map(toCell).join('');
output += white + '\n';
});
output += border;
// 出力
console.log(output);
これで、コマンドラインに大きなQRコードが表示されます。以下の図のようになります:
[caption id="attachment_1323" align="alignnone" width="625"]
terminal-qrcode[/caption]
3. コマンドライン向けの最適化
しかし、コマンドラインで表示すると、サイズが大きすぎます。
QRコードの最小サイズでも 21x21 で、黒い枠の中に 21 行あるとデフォルトの画面1枚をほぼ占有してしまいます。少し長いコードになると全体が表示されなくなりますが、一般的な URL は 21 行を超えます。例えば:
// 誤り訂正レベルが M(デフォルト)の場合
// 21行のQRコードは14文字までしか表示できません
https://www.ay
// 22行の場合は26文字まで表示できます
https://www.ayqy.net/blog/
//...
そこで、出力するQRコードの縦横サイズを小さくする方法を考える必要があります。最も簡単なのは、特殊な Unicode 文字を使って組み立てることです:
[caption id="attachment_1325" align="alignnone" width="484"]
unicode-block[/caption]
さらに列のスペース数を半分に減らせば、幅と高さの両方を半分に縮小できます。以下のようになります:
[caption id="attachment_1326" align="alignnone" width="768"]
terminal-qrcode-small[/caption]
少し見た目は悪いですが、十分に使えます。では、もっと小さく、例えばさらに半分(合計4分の1)に縮小することはできるでしょうか?
同じ方法では不可能です。なぜなら Unicode 文字には「下4分の1ブロック」、「下4分の3ブロック」、「左4分の3ブロック」、「左4分の1ブロック」などは存在せず、足りないからです。
3. オープンソース npm パッケージ
幸運なことに、前述したすべてのことをすでに行っている人がいます:qrcode-terminal-alpha
コマンドラインQRコードをワークフローツールに追加すれば、ビルド完了後に直接QRコードが表示され、スキャンが非常に便利になります。
参考資料
-
QR Code Generator:オンラインQRコード生成器
コメントはまだありません