web-dev-qa-db-fra.com

Décodage base64 de POST à utiliser dans PIL

Je crée une API simple en Flask qui accepte une image encodée en base64, puis la décode pour un traitement ultérieur à l'aide de Pillow.

J'ai regardé quelques exemples ( 1 , 2 , ), et je pense que j'obtiens l'essentiel du processus, mais je garde obtenir une erreur où Pillow ne peut pas lire la chaîne que je lui ai donnée.

Voici ce que j'ai jusqu'à présent:

import cStringIO
from PIL import Image
import base64

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

ce qui donne l'erreur:

IOError: cannot identify image file <cStringIO.StringIO object at 0x10f84c7a0>
39
Lazaro Gamio

Vous devriez essayer quelque chose comme:

from PIL import Image
from io import BytesIO
import base64

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

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

Votre data['img'] la chaîne ne doit pas inclure les balises HTML ou les paramètres data:image/jpeg;base64 qui sont dans l'exemple JSFiddle.

J'ai changé la chaîne d'image pour un exemple que j'ai pris de Google juste à des fins de lisibilité.

69
André Teixeira

Il existe un préfixe de métadonnées de data:image/jpeg;base64, étant inclus dans le champ img. Normalement, ces métadonnées sont utilisées dans un URI de données CSS ou HTML lors de l'incorporation de données d'image dans le document ou la feuille de style. Il est là pour fournir le type MIME et l'encodage des données incorporées au navigateur de rendu.

Vous pouvez supprimer le préfixe avant le décodage base64 et cela devrait se traduire par des données d'image valides que PIL peut charger (voir ci-dessous), mais vous devez vraiment vous demander comment les métadonnées sont soumises à votre serveur comme cela ne devrait normalement pas.

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))
25
mhawke

Désolé pour la nécromancie, mais aucune des réponses n'a fonctionné complètement pour moi. Voici le code qui fonctionne sur Python 3.6 et Flask 0.13.

Serveur:

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'}

Client 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);
5
cyberj0g