Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decoding base64 from POST to use in PIL

I'm making a simple API in Flask that accepts an image encoded in base64, then decodes it for further processing using Pillow.

I've looked at some examples (1, 2, 3), and I think I get the gist of the process, but I keep getting an error where Pillow can't read the string I gave it.

Here's what I've got so far:

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

which gives the error:

IOError: cannot identify image file <cStringIO.StringIO object at 0x10f84c7a0> 
like image 874
Lazaro Gamio Avatar asked Sep 27 '14 01:09

Lazaro Gamio


People also ask

How do I decode a Base64 encoded file?

To decode a file with contents that are base64 encoded, you simply provide the path of the file with the --decode flag. As with encoding files, the output will be a very long string of the original file. You may want to output stdout directly to a file.

Is it possible to decode Base64?

Base64 is an encoding, the strings you've posted are encoded. You can DECODE the base64 values into bytes (so just a sequence of bits). And from there, you need to know what these bytes represent and what original encoding they were represented in, if you wish to convert them again to a legible format.

How do I use Base64 decoding in python?

To decode an image using Python, we simply use the base64. b64decode(s) function. Python mentions the following regarding this function: Decode the Base64 encoded bytes-like object or ASCII string s and return the decoded bytes.

Why do Base64 strings end with ==?

Q Why does an = get appended at the end? A: As a short answer: The last character ( = sign) is added only as a complement (padding) in the final process of encoding a message with a special number of characters.


2 Answers

You should try something like:

from PIL import Image from io import BytesIO import base64  data['img'] = '''R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrLl N48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=='''   im = Image.open(BytesIO(base64.b64decode(data['img']))) 

Your data['img'] string should not include the HTML tags or the parameters data:image/jpeg;base64 that are in the example JSFiddle.

I've changed the image string for an example I took from Google just for readability purposes.

like image 146
André Teixeira Avatar answered Oct 04 '22 03:10

André Teixeira


There is a metadata prefix of data:image/jpeg;base64, being included in the img field. Normally this metadata is used in a CSS or HTML data URI when embedding image data into the document or stylesheet. It is there to provide the MIME type and encoding of the embedded data to the rendering browser.

You can strip off the prefix before the base64 decode and this should result in valid image data that PIL can load (see below), but you really need to question how the metadata is being submitted to your server as normally it should not.

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)) 
like image 22
mhawke Avatar answered Oct 04 '22 02:10

mhawke