1

I want to send an image by POST method to server (e.g by Postman), and then send back the same image to user. Here's what I have and i have no idea how to put image back to user with some response like 200, .

from flask import Flask, request, Response, send_file, jsonify
from PIL import Image
app = Flask(__name__)

@app.route('/')
def index():
    return 'Server Works!'


@app.route('/processing', methods=['POST'])
def process():
    file = request.files['image']
    img = Image.open(file.stream)
    
    return jsonify({'msg': 'success', 'size': [img.width, img.height]})

This correctly get image and send back some informations like width and height, but what I want is to return the same image with response code. Thank's for suggestions

shaman7
  • 23
  • 1
  • 4
  • 1
    Flask has `send_file()` to send image saved on disk - but using `io.BytesIO` you could send also data from memory - but this sends only image without other values. Did you try simply add image to you json data ? something like `jsonify({'img': file.stream.read()})` ? But then browser would have to use JavaScript to display it. If you want to send image after some changes then you could use again `io.BytesIO` for this. And this was described few times on Stackoverflow. – furas Apr 21 '21 at 14:01

1 Answers1

4

If you would send only image then you could use send_file() to send it as is (as bytes). And then browser could display it directly.

But if you want to send image with other values in JSON then you have to convert it from bytes to base64 and add to JSON

data = file.stream.read()
data = base64.encodebytes(data)

return jsonify({'msg': 'success', 'size': [img.width, img.height], 'img': data})

And later you would need JavaScript code to convert it back and display using canvas in browser - or it create <img> using base64 in url -

for jpeg:

<img src="data:image/jpeg;base64,...base64 data...">

for png:

<img src="data:image/png;base64,...base64 data...">

so you would have to send also information what image it is - JPG or PNG.

img.format

Minimal working code which send image in JSON

from flask import Flask, request, jsonify
from PIL import Image
import base64

app = Flask(__name__)

@app.route('/')
def index():
    return '''Server Works!<hr>
<form action="/processing" method="POST" enctype="multipart/form-data">
<input type="file" name="image">
<button>OK</button>
</form>    
'''

@app.route('/processing', methods=['POST'])
def process():
    file = request.files['image']
    
    img = Image.open(file.stream)
    
    data = file.stream.read()
    #data = base64.encodebytes(data)
    data = base64.b64encode(data).decode()   

    return jsonify({
                'msg': 'success', 
                'size': [img.width, img.height], 
                'format': img.format,
                'img': data
           })
    
if __name__ == '__main__':
    app.run(debug=True)

If you want to send image after changes (without writing on disk) then would need to use io.Bytes() to convert object PIL.Image to compressed file in memory.

I also show how to use base64 image directly in HTML

@app.route('/processing', methods=['POST'])
def process():
    file = request.files['image']
    
    img = Image.open(file.stream)
    img = img.convert('L')   # ie. convert to grayscale

    #data = file.stream.read()
    #data = base64.b64encode(data).decode()
    
    buffer = io.BytesIO()
    img.save(buffer, 'png')
    buffer.seek(0)
    
    data = buffer.read()
    data = base64.b64encode(data).decode()
    
    #return jsonify({
    #            'msg': 'success', 
    #            'size': [img.width, img.height], 
    #            'format': img.format,
    #            'img': data
    #       })

    return f'<img src="data:image/png;base64,{data}">'
furas
  • 134,197
  • 12
  • 106
  • 148