How to show image from body of post request in flask api?

Question:

I am trying to display the image captured from the browser/html canvas. A user would basically draw something, and I want to send it to my flask api so i can further process it with opencv, but i am having trouble just displaying the image.

HTML

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]>      <html class="no-js"> <!--<![endif]-->
<html>
<head>
  <title>Drawing Tool</title>
  <style>
    canvas {
      border: 1px solid black;
    }
  </style>
</head>
<body>
  <h1>Drawing Tool</h1>
  <canvas id="canvas" width="400" height="300"></canvas>
  <button id="clear-button">Clear</button>
  <button id="submit-button">Submit</button>
  <script src="index.js"></script>
</body>
</html>

index.js

submitButton.addEventListener('click', function (e) {
  canvas.toBlob((blob) => {
    var formData = new FormData()
    formData.append('image', blob, 'image.jpg')
    fetch('http://localhost:105/sendImg', {
      method: "POST",
      body: formData
    })
      .then(response =>
        console.log(response)
      )
      .catch(err =>
        console.log(err)
      )
  }, 'image/jpeg', 0.95);
});

server.py

app = Flask(__name__)
CORS(app)

@app.route('/sendImg', methods=['POST'])
def showImage(): 
    file = request.files['image']
    file.save('image.jpg')
    with open('image.jpg', 'rb') as f:
        image = Image.open(io.BytesIO(f.read()))
    image.save('processed_image.jpg')
    image.show()

    return 'OK'

Asked By: benwl

||

Answers:

I tried your code and, at least on my environment (see at the bottom for more details), it worked after I added a few pieces here and there that were missing from your examples, I assume because your examples were/are part of a bigger application.

How I made it work

The additions and changes:

  1. In the HTML, I added a script element to the end of the body element to draw something on the canvas, and I added a piece of code to convert the canvas to an image element that I show on the same HTML page for verification:

      <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');
    
        // Draw circle
        ctx.arc(120, 120, 100, 0, Math.PI * 2);
        ctx.strokeStyle = 'pink';
        ctx.fillStyle = 'yellow';
        ctx.lineWidth = 4;
        ctx.fill();
        ctx.stroke();
    
        // Add canvas image on the page for verification
        canvas.toBlob((blob) => {
        const newImg = document.createElement("img");
        const url = URL.createObjectURL(blob);
        newImg.onload = () => {
            // no longer need to read the blob so it's revoked
            URL.revokeObjectURL(url);
        };
        newImg.src = url;
        document.body.appendChild(newImg);
        });
      </script>
    
    
  2. In index.js, I changed the port to the default 5000 and added the following line to the beginning of the file to define the submit button:

    const submitButton = document.getElementById('submit-button');
    
  3. In server.py, I added the missing imports to the beginning of the file:

    from flask import Flask, request
    from flask_cors import CORS
    from PIL import Image
    
    import io
    

How I tested it

  1. I ran the server on the terminal with:

    flask -app server run
    
  2. I opened the HTML file in the browser, saw that it drew the circle on the canvas and added the saved image on the page.

  3. I then clicked on the submit button and was shown the uploaded image (black background with a pink circle filled with yellow).

Suggestions

In your comment, you mentioned:

When I click the html button, I get an image that pops up but its just a black box. I expect the image to be whatever I drew on the HTML canvas.

It sounds like uploading the image to the Flask server works, so I think the problem is not in Flask.

Because it sounds like drawing is not saved, I would use the verification code part that I added to the index.js to see that the code used to draw on the canvas actually works and that it can be saved as an image. This helps see and verify the result before it is uploaded as a file.

My environment

older macOS
latest Firefox

Python 3.9.13
Pip 22.0.4

Flask 2.3.2
Flask-Cors 3.0.10
Pillow 9.5.0

Answered By: Jarno Lamberg
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.