python - Decodificación base64 de POST para usar en PIL
flask python-imaging-library (3)
Estoy haciendo una API simple en Flask que acepta una imagen codificada en base64, luego la decodifica para su posterior procesamiento con Pillow.
He visto algunos ejemplos ( 1 , 2 , 3 ), y creo que entiendo la esencia del proceso, pero sigo recibiendo un error donde Pillow no puede leer la cadena que le di.
Esto es lo que tengo hasta ahora:
import cStringIO
from PIL import Image
import base64
data = request.form
image_string = cStringIO.StringIO(base64.b64decode(data[''img'']))
image = Image.open(image_string)
que da el error:
IOError: cannot identify image file <cStringIO.StringIO object at 0x10f84c7a0>
Hay un prefijo de metadatos de data:image/jpeg;base64,
se incluye en el campo img
. Normalmente, estos metadatos se utilizan en un URI de datos CSS o HTML cuando se incorporan datos de imagen en el documento o en la hoja de estilo. Está allí para proporcionar el tipo MIME y la codificación de los datos integrados en el navegador de renderizado.
Puedes quitar el prefijo antes de la decodificación base64 y esto debería dar como resultado datos de imagen válidos que PIL puede cargar (ver a continuación), pero realmente necesitas cuestionar cómo los metadatos se envían a tu servidor como normalmente no debería.
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))
Deberías probar algo como:
Voy a cambiar la cadena de imagen para un ejemplo que tomé de Google solo para fines de legibilidad.
from PIL import Image
from io import BytesIO
import base64
data[''img''] = ''''''R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw==''''''
im = Image.open(BytesIO(base64.b64decode(data)))
Su cadena de datos [''img''] no debe incluir las etiquetas html ni los datos de parámetros : image / jpeg; base64, que se encuentran en el ejemplo jsfiddle.
Perdón por la nigromancia, pero ninguna de las respuestas funcionó por completo para mí. Aquí está el código trabajando en Python 3.6 y Flask 0.13.
Servidor:
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''}
Cliente 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);