IchigoJam + MixJuice でQRコードを表示する

今日は12月4日。
11月34日という見方もできる。
1134 といえば、[文化放送](https://www.joqr.co.jp/)のAMの周波数 [kHz]。
文化放送といえば、QR。

そこで、今回は [IchigoJam](https://ichigojam.net/) でQRコードを表示してみた。
表示するデータは、[MixJuice](http://mixjuice.shizentai.jp/) を用いて取得するようにした。

※IchigoJamはjig.jpの登録商標です。
※「QRコード」は株式会社デンソーウェーブの登録商標です。

# QRコードを作成するAPI

今回は、このAPIを用いる。

[QR code API](https://goqr.me/api/)

CORS・HTTPS対応で、Webからも使用できる。
さらに、設定によって IchigoJam でも扱いやすいテキスト形式でQRコードを出力できる。

:::note warn
この「テキスト形式」の中身の仕様は明文化されておらず、今後変わる恐れがある。
今回のプログラムは、この変わる恐れのある仕様に依存している。
:::

ただし、(執筆時点において) [Terms of Service のページ](https://goqr.me/legal/tos-api.html)があるが、そこにはタイトルと日付が書かれているのみで規約の内容は書かれていないようである。
これは、少し心配になる点である。

## 今回用いる入力

URLのクエリストリングとして、QRコードの生成に用いる情報を設定する。

### data

QRコードに格納するデータを指定する。

別のパラメータ (今回は使用しない) の説明によると、使える文字コードは [ISO-8859-1](https://ja.wikipedia.org/wiki/ISO/IEC_8859-1) または [UTF-8](https://ja.wikipedia.org/wiki/UTF-8) のようであるが、どちらでもない IchigoJam のカタカナの文字コード (Shift_JIS 互換) をそのまま入れても、数種類のリーダーで問題なく読めるQRコードが生成できるようだった。

### format

出力するQRコードの画像形式を指定する。
数種類の中から選ぶことができ、`eps` を指定することで IchigoJam でも扱いやすいテキスト形式の出力が (今のところ) 得られる。

## 今回用いる出力

例として、

```text
https://api.qrserver.com/v1/create-qr-code/?format=eps&data=hello
```

にアクセスすると、以下のようなデータが得られた。

```postscript
%!PS-Adobe EPSF-3.0
%%Creator: https://api.qrserver.com (QR Code API, see goQR.me/api for information)
%%Title: qr-code
%%CreationDate: 2024-12-02
%%Pages: 1
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
%%BoundingBox: 0 0 21 21
%%EndComments
%%Page: 1 1
%%BeginPageSetup
%%PageBoundingBox: 0 0 21 21
%%EndPageSetup
1 1 scale
0 0 translate
1 1 1 setrgbcolor
0 0 21 21 rectfill
0 0 0 setrgbcolor
newpath
0 0 moveto
1 0 lineto
1 1 lineto
0 1 lineto
0 0 lineto
1 0 moveto
2 0 lineto
2 1 lineto
1 1 lineto
1 0 lineto
2 0 moveto
3 0 lineto
3 1 lineto
2 1 lineto
2 0 lineto
(中略)
19 20 moveto
20 20 lineto
20 21 lineto
19 21 lineto
19 20 lineto
20 20 moveto
21 20 lineto
21 21 lineto
20 21 lineto
20 20 lineto
closepath
fill
%%EOF
```

この中で、

```postscript
0 0 21 21 rectfill
```

の部分が生成された画像の大きさを表し、

```postscript
0 0 moveto
```

の部分がQRコードを構成する四角を描画する位置を表しているようである。

さらに、改行コードは LF で、`%%EOF` に続く改行が最後のデータのようである。
そこで、今回はこれらの値をもとにQRコードの描画を行う。

# 実装

`POS` や `DRAW` を用いているので、1.4系(以降)専用である。

```text
10 ' 2ｼﾞｹﾞﾝ ｺｰﾄﾞ ﾋｮｳｼﾞ
20 CLS:?"2ｼﾞｹﾞﾝ ｺｰﾄﾞ ﾆ ｽﾙ ﾃｷｽﾄ ｲﾚﾃ Enter"
30 W=POS(3)*2:H=POS(4)*2:A=#900+POS():INPUT "",X
40 LOCATE0,-1:?CHR$(#0A);"MJ GETS api.qrserver.com/v1/create-qr-code/?format=eps&data=";
50 C=PEEK(A):IFC?"%";HEX$(C,2);:A=A+1:GOTO50ELSE?""
60 CLS:X=0:Y=0:Z=0:E=0:F=0
70 P=C
80 C=INKEY():IF!CGOTO80
90 IFFANDC=#0A:GOTO150
100 IFC=#0AORC=#20:X=Y:Y=Z:Z=0:GOTO70
110 IFP=#65ANDC=#63:U=(W-X)/2:V=H-1-(H-Y)/2:E=1:GOTO70
120 IFEANDC=#6D:DRAWU+X,V-Y:GOTO70
130 IFC=#4F:F=1:GOTO70
140 Z=Z*10+C-#30:GOTO70
150 IF INKEY() GOTO20 ELSE GOTO150
```

30行目で、画面の大きさと入力を読み取るアドレスを取得し、文字列の入力を受け付ける。
このとき、`INPUT` が変数に格納する内容は用いず、あとで画面から直接文字列を読み取る。

40～50行目で、MixJuice 経由でAPIにリクエストを送る。
特殊文字かの判定は面倒なので、テキストはすべてURLエンコードして送る。

60行目で、APIが返す出力の処理用の状態を初期化する。
70～80行目で、APIから文字を読み取り、前回の文字 `P` と今回の文字 `C` を用意する。

90～140行目で、APIが返す出力の処理を行う。

* 90行目：`O` (`%%EOF`) が来た後で改行が来たら、処理を終了する
* 100行目：改行または空白が来たら、数値を区切る
* 110行目：`ec` (`rectfill`) が来たら、画像の大きさと画面の大きさをもとに描画する位置を (画面中央に) 決定する
* 120行目：`ec` が来た後で `m` (`moveto`) が来たら、直前2個の数値を座標として点を打つ。このとき、最初の数値を右が正のx座標、次の数値を上が正のy座標として扱うとうまく描画できるようである
* 130行目：`O` が来たら、フラグを立てる
* 140行目：その他の入力は数値を構成する文字とみなし、数値を更新する

150行目で、QRコードの描画が完了後、キーが押されたら最初に戻って次の文字列の入力を受け付ける。

# 実行例

テキストを入力する。

![実行例1 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/88b0b877-effb-217a-f4d0-ae39d07258dc.png)

そして、Enterキーを押してしばらく待つと、QRコードが表示される。

![実行例1 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/3e42fd46-5b97-268e-3148-e37d9d9529a3.png)

MixJuice デフォルトのウェイトだと長時間かかってしまうが、ウェイトを減らしすぎると表示に支障が出ることがある。
IchigoJam Q (IchigoJam BASIC 1.4.3) では、

```text
?"MJ SPW 15
```

を実行後、今回のプログラムを実行するのが良さそうだ。

もう少し長いテキストを入力してみる。

![実行例2 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/27af669a-c028-87d6-1669-22abc2cd4a65.png)

QRコードを表示できた。

![実行例2 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/6c3df7fd-16c0-7f53-028d-0dd9b2e9aee6.png)

事前に `VIDEO2` を実行し、黒白ではなく白黒で表示させてみる。

![実行例3 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/4e947ea3-64fd-10dc-3318-c388335c4366.png)
![実行例3 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/0bc46965-09ff-3595-8a43-193baab0a045.png)

もう少しテキストを長くすると、途中で表示が止まってしまった。
どうやら、MixJuice で受信できるレスポンスのサイズの限界に引っかかってしまったようだ。

![実行例4 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/47b69a87-63d0-661a-2840-b70cc81e7be4.png)
![実行例4 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/1a673119-0943-7ef0-8a4f-ee636268ccba.png)

行が変わるとキャレットを戻しにくくなる (Homeで最初には戻れるが、左矢印では行を超えて戻れないようである)、カタカナ入力に支障が出る (ローマ字が行の区切りに当たってしまうと、うまく変換されずアルファベットが残ってしまうことがある) といった現象が発生することもあり、入力するテキストは1行分までにするのがよさそうだ。

事前に `VIDEO3` を実行し、拡大表示してみた。
コード本体は画面に収まったが、クワイエットゾーンははみ出してしまう。

![実行例5 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/002e21ac-2cd0-bc77-4241-2365741fff94.png)
![実行例5 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/e352d0cc-f004-9dbb-83b2-df23417003d2.png)

もう少しテキストを長くすると、コード本体もはみ出してしまった。

![実行例6 入力](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/6051b1d6-0d5a-3a7e-ab49-579b0dcb37df.png)
![実行例6 結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99656/8f3f37ce-7eaf-f911-9849-66da1ddb6651.png)

# まとめ

MixJuice を用いてAPIでQRコードを生成し、IchigoJam で描画した。
今回用いたAPIは今のところ処理しやすいテキスト形式でQRコードを出力できるので、将来出力形式が変更されて動かなくなる恐れはあるが、この形式に依存する形で実装を行った。

実行してみると、大きなQRコードを生成すると MixJuice で受信できるレスポンスのサイズの限界を超えてしまうようなので、入力するテキストは1行分 (32文字) までが実用のようだ。
より効率のよい形式でレスポンスを返すAPIを用意すれば、より大きなQRコードを表示できる可能性はある。