戦車ラジコン：QRコードに画像貼り付け

[戦車ラジコンネタ](https://qiita.com/poruruba/items/0c814783f89f42e65933) はまだ続きます。
M5CameraでQRコードを探していましたが、今回は、発見したQRコードに画像を張り付けて、より敵キャラっぽくしてみようと思います。

まずは通常のQRコードを発見したとき。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/dc343466-da92-46f1-4594-19510848b0ae.png)

こっちが、画像のQRコードを発見したときです。敵戦車の画像がはめ込まれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/b4dd4ffd-3ab0-5a95-be4f-325df40a5cb6.png)

毎度の通り、GitHubに上げておきました。
　https://github.com/poruruba/obniz_motor

以下からもページを参照できます。（Obnizにつながないと使えないですが）。
　https://poruruba.github.io/obniz_motor/
※M5Cameraがhttp接続なので、https上にある上記ページからは解像度の変更ができないようです。

# 画像の変形

発見したQRコードは、見る角度によって、正方形ではなく、遠近法によって台形状になっていたり、斜めになっていたりします。
そこで、はめ込む画像をそれに合わせて変形します。
以下のサイトをそのまま使わせていただきました。（ありがとうございました）

4角形の変形
　http://oldmist.html.xdomain.jp/game_make/t001.html 

```js:start.js
function drawTexture(g, img, plsttx){
    var imgw = img.width;
    var imgh = img.height;

    var m11 = (plsttx[1].x - plsttx[0].x) / imgw;
    var m12 = (plsttx[1].y - plsttx[0].y) / imgw;
    var m21 = (plsttx[3].x - plsttx[0].x) / imgh;
    var m22 = (plsttx[3].y - plsttx[0].y) / imgh;
    var dx = plsttx[0].x;
    var dy = plsttx[0].y;

    try{
        g.save();
        g.beginPath();
        g.moveTo(plsttx[0].x, plsttx[0].y);
        g.lineTo(plsttx[1].x, plsttx[1].y);
        g.lineTo(plsttx[3].x, plsttx[3].y);
        g.closePath();
        g.clip();
        g.setTransform(m11, m12, m21, m22, dx, dy);
        g.drawImage(img, 0, 0);
        g.restore();
    
        m11 = (plsttx[2].x - plsttx[3].x) / imgw;
        m12 = (plsttx[2].y - plsttx[3].y) / imgw;
        m21 = (plsttx[2].x - plsttx[1].x) / imgh;
        m22 = (plsttx[2].y - plsttx[1].y) / imgh;
        dx = plsttx[1].x - imgw * m11;
        dy = plsttx[3].y - imgh * m22;
    
        g.save();
        g.beginPath();
        g.moveTo(plsttx[1].x, plsttx[1].y);
        g.lineTo(plsttx[2].x, plsttx[2].y);
        g.lineTo(plsttx[3].x, plsttx[3].y);
        g.closePath();
        g.clip();
        g.setTransform(m11, m12, m21, m22, dx, dy);
        g.drawImage(img, 0, 0);
        g.restore();
    }catch(error){
        console.log(error);
        g.restore();
    }
}
```

この関数を、QRコードを発見したときに呼び出します。
ただし、発見したQRコードの拡張子が.pngのときだけ上記関数を呼び出しています。

```js:start.js
    if( this.qrcode_list.indexOf(code.data) < 0){
        this.qrcode = code.data;
        this.lockon = true;

        var pos = code.location;
        this.qrcode_context.beginPath();
        this.qrcode_context.moveTo(pos.topLeftCorner.x, pos.topLeftCorner.y);
        this.qrcode_context.lineTo(pos.topRightCorner.x, pos.topRightCorner.y);
        this.qrcode_context.lineTo(pos.bottomRightCorner.x, pos.bottomRightCorner.y);
        this.qrcode_context.lineTo(pos.bottomLeftCorner.x, pos.bottomLeftCorner.y);
        this.qrcode_context.lineTo(pos.topLeftCorner.x, pos.topLeftCorner.y);
        this.qrcode_context.stroke();

        if( this.qrcode.toLowerCase().endsWith('.png') ){
            var img = this.enemy_list.get(this.qrcode);
            if( !img ){
                var image = new Image();
                image.crossOrigin = "Anonymous";
                image.src = this.qrcode;
                img = { image: image, count: 0 };
                this.enemy_list.set(this.qrcode, img );
            };
            drawTexture(this.qrcode_context, img.image, [pos.topLeftCorner, pos.topRightCorner, pos.bottomRightCorner, pos.bottomLeftCorner]);
        }else if( this.qrcode.toLowerCase().endsWith('.mp3') ){
            if( this.audio == null ){
                this.audio = new Audio();
                this.audio.addEventListener("ended", () => this.audio = null, false);
                this.audio.src = this.qrcode;
                this.audio.play();
            }
        }
```

# 補足

・変形させた画像に、斜めに白い線がでちゃうんですが、消し方がわからない。。。
・QRコードの検出がシビアな場合、画像が表示されたり消えたりで、ちかちかします。
・QRコードから画像を取得する場合、ここでも汚染が影響します。同じドメインに画像を配置してください。


# おまけ：QRコードの的の作り方

Choromeブラウザとプリンタを使います。

まずは、以下のページを開きます。

https://poruruba.github.io/utilities/
　(参考) [便利ページ：Javascriptでちょっとした便利な機能を作ってみた](https://qiita.com/poruruba/items/6c67c7eef34ed302feb3)

QRコードタブの「QRコード生成」の入力に、画像のURLを入力し、「生成」ボタンを押下します。
（例えば、https://poruruba.github.io/obniz_motor/img/tank.png ）

すると、QRコードが表示されます。
その画像の上で、右クリックし、「新しいタブで画像を開く」を選択すると、別のタブにQRコードだけ表示されます。
そのタブ上で、右クリックし、「印刷」を選択して、プリンタで紙に印刷します。

あとは、以下のように折りたためば、QRコード的(まと)の完成です。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/5173c103-d7c9-7277-9701-5e26cbcaf57f.png)

※上下逆さまにすると、表示される画像も逆さまになるので注意です。（とはいっても、どっちが上かわかりにくいですが）

以上