2014-09-27 11 views
20

Ich mache eine einfache API in Flask, die ein in base64 codiertes Bild akzeptiert, dekodiert es dann für die weitere Verarbeitung mit Kissen.Decoding base64 von POST in PIL zu verwenden

Ich habe einige Beispiele sah (1, 2, 3), und ich denke, dass ich den Kern des Prozesses, aber ich halte einen Fehler bekommen, wo Kissen kann die Zeichenfolge nicht lesen ich es gab.

Hier ist, was ich bisher habe:

import cStringIO 
from PIL import Image 
import base64 

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

, die den Fehler verursacht:

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

Können Sie in einem Beispiel einfügen, was Sie bekommen in 'data [ 'img']'? Protokollieren Sie das oder drucken Sie es aus. – OregonTrail

+0

Hier ist ein Beispiel: http://jsfiddle.net/gn0x0wvc/. Ich habe es in ein "img" -Tag eingefügt, um sicherzustellen, dass die Bilddaten nicht beschädigt wurden. –

+0

Wie sehen die Daten nach 'b64decode()' aus? Gibt es irgendeine andere Kodierung, z. Urlencodierung? Ist es wirklich ein Bild, das von PIL unterstützt wird? – mhawke

Antwort

39

Sie so etwas wie versuchen sollte:

Ich werde das Bild Zeichenfolge für eine ändern Beispiel, das ich aus Gründen der Lesbarkeit von Google übernommen habe.

from PIL import Image 
from io import BytesIO 
import base64 

data['img'] = '''R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==''' 

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

Ihre Daten [ 'img'] string sollten die HTML-Tags enthalten, oder die Parameter Daten: image/jpeg; base64,, die im Beispiel jsfiddle sind.

+2

Vielen Dank! Das hat perfekt funktioniert. Ich habe deine Antwort richtig markiert. –

16

Im Feld data:image/jpeg;base64, ist ein Metadatenpräfix von img enthalten. Normalerweise werden diese Metadaten in einem CSS- oder HTML-Daten-URI verwendet, wenn Bilddaten in das Dokument oder Stylesheet eingebettet werden. Es ist da, um den MIME-Typ und die Codierung der eingebetteten Daten dem Rendering-Browser bereitzustellen.

Sie können das Präfix vor der base64-Dekodierung entfernen und dies sollte zu gültigen Bilddaten führen, die PIL laden kann (siehe unten), aber Sie müssen wirklich fragen, wie die Metadaten an Ihren Server übermittelt werden nicht.

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)) 
+0

Vielen Dank! Das hat perfekt funktioniert! –

+0

@LazaroGamio: Der Hauptpunkt ist jedoch, dass das Präfix nicht in den Daten auf Ihrem Server vorhanden sein sollte. Wie wird es gepostet? – mhawke

+0

Ich nehme ein vom Benutzer hochgeladenes Bild und sende es über die jquery-post-Methode an die API.Ich nehme an, ich könnte das Präfix von der Clientseite entfernen, anstatt es auf dem Server zu entfernen. –

1

Sorry für Nekromantie, aber keine der Antworten funktionierte vollständig für mich. Hier ist Code, der an Python 3.6 und Flask 0.13 arbeitet.

Server:

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 Auftraggeber:

// 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);