Подтвердить что ты не робот

Декодирование base64 от POST для использования в PIL

Я делаю простой API в Flask, который принимает изображение, закодированное в base64, а затем декодирует его для дальнейшей обработки с помощью Pillow.

Я рассмотрел несколько примеров (1, 2, 3), и я думаю, что получаю суть процесса, но я все время получаю сообщение об ошибке, когда Pillow не может прочитать строку, которую я ей дал.

Вот что у меня до сих пор:

import cStringIO
from PIL import Image
import base64

data = request.form
image_string = cStringIO.StringIO(base64.b64decode(data['img']))
image = Image.open(image_string)

который дает ошибку:

IOError: cannot identify image file <cStringIO.StringIO object at 0x10f84c7a0>
4b9b3361

Ответ 1

Вы должны попробовать что-то вроде:

from PIL import Image
from io import BytesIO
import base64

data['img'] = '''R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLl
N48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==''' 

im = Image.open(BytesIO(base64.b64decode(data)))

Строка data['img'] не должна содержать теги HTML или параметры data:image/jpeg;base64 которые есть в примере JSFiddle.

Я изменил строку изображения для примера, взятого из Google только для удобства чтения.

Ответ 2

В поле img включен префикс метаданных data:image/jpeg;base64,. Обычно эти метаданные используются в URI данных CSS или HTML при встраивании данных изображения в документ или таблицу стилей. Он должен предоставить тип MIME и кодирование встроенных данных в браузер визуализации.

Вы можете отключить префикс до декодирования base64, и это должно привести к действительным данным изображения, которые может загрузить PIL (см. ниже), но вам действительно нужно задать вопрос о том, как метаданные отправляются на ваш сервер, как обычно это не должно.

import re
import cStringIO
from PIL import Image

image_data = re.sub('^data:image/.+;base64,', '', data['img']).decode('base64')
image = Image.open(cStringIO.StringIO(image_data))

Ответ 3

Извините за некромантию, но ни один из ответов не работал полностью для меня. Вот код, работающий на Python 3.6 и Flask 0.13.

Сервер:

from flask import Flask, jsonify, request
from io import BytesIO
from web import app
import base64
import re
import json
from PIL import Image

@app.route('/process_image', methods=['post'])
def process_image():
    image_data = re.sub('^data:image/.+;base64,', '', request.form['data'])
    im = Image.open(BytesIO(base64.b64decode(image_data)))
    return json.dumps({'result': 'success'}), 200, {'ContentType': 'application/json'}

Клиент JS:

// file comes from file input
var reader = new FileReader();
reader.onloadend = function () {
    var fileName = file.name;
    $.post('/process_image', { data: reader.result, name: fileName });
};
reader.readAsDataURL(file);