LoginSignup
2
4

More than 3 years have passed since last update.

PythonのFlaskで画像データをreturnし、HTMLのcanvas要素へ描写する

Last updated at Posted at 2020-10-19

PythonのFlaskで取得した画像データをHTMLのcanvas要素へ描写します。

やりたいこと

Google Cloud Storageに保存した画像データをCloud functionsで読み出して、手元のHTMLのcanvas要素に描写します。Cloud functionsでは画像イメージがまずはblob形式で読み出されます。これをpngやjpgに変換してflaskでreturnして、canvas要素で描写します。

Cloud functionsでStorageのファイルを読み込んでダウンロードする

ここは公式ドキュメントが充実しているので迷いませんでした。

main.py
from google.cloud import storage

def download_blob(bucket_name, source_blob_name, destination_file_name):
    """Downloads a blob from the bucket."""
    # bucket_name = "your-bucket-name"
    # source_blob_name = "storage-object-name"
    # destination_file_name = "local/path/to/file"

    storage_client = storage.Client()

    bucket = storage_client.bucket(bucket_name)
    #bucket_nameとは、Storageに作った格納先の名前。手動で設定したもの

    blob = bucket.blob(source_blob_name)#要するにファイル名
    blob.download_to_filename(destination_file_name)

    print(
        "Blob {} downloaded to {}.".format(
            source_blob_name, destination_file_name
        )
    )

実行するとローカルにファイルがダウンロードされます。

単体ファイルとしてダウンロードさせるのではなく、flaskでjpgとしてreturnしてダウンロードする

この辺で詰まり始めた。要するに、blobをbytesで読んで、それにheaderなどをつけて画像としてreturnする。その際、Flaskのsend_fileというモジュールを使う。いや、これわからんでしょ。

なお、今回はホスティングはGCPのCloud functionsでやっているので、app.run()などはありません。ただこれをホスティングすると、あるURLを叩いたらdownload_blob()の関数が動きます。

main.py
from google.cloud import storage
import io
from flask import send_file

def download_blob(request):
    """Downloads a blob from the bucket."""
    bucket_name = "your-bucket-name"
    source_blob_name = "storage-object-name"

    storage_client = storage.Client()

    bucket = storage_client.bucket(bucket_name)
    #bucket_nameとは、Storageに作った格納先の名前。手動で設定したもの

    blob = bucket.blob(source_blob_name)#要するにファイル名
    image_binary= blob.download_as_bytes()
    return send_file(
            io.BytesIO(image_binary),
            mimetype='image/jpeg',
            as_attachment=True,
            attachment_filename='%s.jpg' % source_blob_name)

Cloud functionsでのデプロイは下記を参考に。
https://qiita.com/NP_Systems/items/f0f6de899a84431685ff

ライブラリなどインストールしていたら下記を打つだけで、ローカルでエミュレートします。

teriminal.
functions-framework --target=hello  --port=8081

ホスティングしたURLを叩いたら、画像がダウンロードされます。でも単体ファイルとは違って、returnしています。これを使って、あとは受け取ったものをcanvasへ描写します

canvas要素への描写

ここもかなり詰まりました。こんなシンプルなことなのに。
このサイト本当に助かりました。
https://stackoverflow.com/questions/57014217/putting-an-image-from-flask-to-an-html5-canvas

phpですがhtmlでも同じようなものです。

index.php
<?php get_header(); ?>
<main>
<article>
  <section>
       <input type="button" value="Start" onclick="main();"/>
        <canvas></canvas>
  </section>
</article>
</main>

<script language="javascript" type="text/javascript">

    function main(){
      var canvas = document.getElementsByTagName('canvas');
      var ctx = canvas[0].getContext('2d');

      var img = new Image();
      img.src = 'http://0.0.0.0:8081';//FlaskでホスティングしたURL

      img.onload = function() {
        img.style.display = 'none'; // ようわからん
        console.log('WxH: ' + img.width + 'x' + img.height)

        ctx.drawImage(img, 0, 0);
        var imageData = ctx.getImageData(0, 0, img.width*2, img.height*2)

        for(x = 0 ; x < 100 ; x += 10) {
          for(y = 0 ; y < 100 ; y += 10) {
             ctx.putImageData(imageData, x, y);
          }
        }
      };    }
</script>
<?php get_footer(); ?>

感想

いや、こんなシンプルなことなのに詰まりまくった。blobやpngへの理解が浅い気がする。

2
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4