MotoJapan's Tech-Memo

技術めも

【Javascript to flask】base64で画像を送信/受信する方法 【お家IT#7】

本件の実装の一部 
motojapan.hateblo.jp

前回の続き 
motojapan.hateblo.jp

目次 

前々回、ChromeWebカメラを起動/撮影した後、Canvasに書き出すところまで進めた。
前回は、Ajaxを利用した単純なデータ通信をまとめた。
この流れでCanvasの画像をbase64化してサーバーに送信したい。

やり方がわかると実はすごく単純。

base64とは

データを["a-z", "A-Z", "0-9", "+", "/"]の64文字で表現するエンコード方式
(データは特に画像などに限らない。)

送信側実装(Javascript)

#ajax用モジュール読み込み
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript">
    ...

    function send_img(){
        //canvas elementを取得
        var canvas = document.getElementById('canvas');
        //base64データを取得(エンコード)
        var base64 = canvas.toDataURL('image/png');

        var fData = new FormData();
        fData.append('img', base64);

        #ajax送信
        $.ajax({
            //画像処理サーバーに返す場合
            url: 'https://192.168.0.100:12345/hoge_image_processing',   
            type: 'POST',
            data: fData ,
            contentType: false,
            processData: false,
            success: function(data, dataType) {
                //非同期で通信成功時に読み出される [200 OK 時]
                console.log('Success', data);
            },
            error: function(XMLHttpRequest, textStatus, errorThrown) {
                //非同期で通信失敗時に読み出される
                console.log('Error : ' + errorThrown);
            }
        });
    }
    ...
</script>

受信側実装(python : flask)

import base64
from PIL import Image
from io import BytesIO

...
#前回に追記
@app.route('/hoge_image_processing', methods=['POST'])
def set_data():
    enc_data  = request.form['img']
    #dec_data = base64.b64decode( enc_data )              # これではエラー  下記対応↓
    dec_data = base64.b64decode( enc_data.split(',')[1] ) # 環境依存の様(","で区切って本体をdecode)
    dec_img  = Image.open(BytesIO(dec_data))
...

enc_dataを詳しく見てみると次の通り。

data:image/png;base64,kpvdfkgspkhgsKOJIJgmfkdvmkkPOKPO
DSmkpogj/mKRFPVKMPOGKP+OSKPVKS++LKVOPKIGRPOIJpkvmplldk
iVBaasfdojOIAJHSUHFvDFNIOVEOIJobjtredpjORw0KGgoAAAANSU
hEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4Xky9W4+la5adNb/z
WisiI3Mfq6vbXY1E26ItVcsWssG ...

“data:image/png;base64,”以降がbase64エンコードされた画像情報(エンコードデータ)。
これをpythonで扱えるようにするためには、次の手順が必要。

  • 1. エンコードデータbase64.b64decodeでデコードして、byte列にする。
  • 2. byte列を、BytesIOでバイナリストリームに変換し、PILでpythonで扱える画像形式にする。

以上。

ここまで来てフロントエンドからは 「No 'Access-Control-Allow-Origin' header is present on the requested resource. 」というエラーがでているので、次回はこれを修正する。

あと、Javascript->flaskへの通信が多いが、画像処理結果をWebアプリに送り返したいこともある。
次々回は、flask->Javascriptjsonデータ通信を纏めたい。