Learn how to use Dash Bio for next-gen sequencing & quality control. 🧬 Register for the Oct 27 webinar.

Problem when converting uploaded image in base64 to string or PIL.Image

Hello all

I am facing a huge problem when I’m uploading an image (.jpg or .png) via the dcc.upload component: I have to feed the image into a function that accepts either a string or PIL.Image object. In my opinion it would be better to convert it to a PIL.Image (?). So I have to convert the base64 encoded image to a PIL.Image object but I cannot get this to work. I am able to display the uploaded image in dash though. Please help!

I tried the following: (uploaded image is called upload, function for further use called function)

  • Using upload object itself: OSError: [Errno 63] File name too long: 'data:image/png;base64,iVB...
  • function(base64.b64decode(upload, 'rb')): assert isinstance(image, str) or isinstance(image, Image.Image)
  • function(Image.open(base64.b64decode(upload, 'rb'))): ValueError: embedded null byte
  • function(Image.open(BytesIO(base64.b64decode(upload, 'rb')))): OSError: cannot identify image file <_io.BytesIO object at 0x146225d10>
  • Using upload = base64.b64decode(upload + '===') didn’t help
  • Using ImageFile.LOAD_TRUNCATED_IMAGES = True didn’t help

But the image file can’t be corrupted as I can clearly display it in the browser?
And getting a string (or path) out of it is also not a good idea I think as the image will be uploaded from the user?

Thanks!

Hi @fabmeyer, welcome to the forum! Are you sure the function function accepts a PIL object or an image string? Several error messages complain about an invalid file name, maybe the function is expecting a path instead? If it’s confirmed that a PIL object is accepted, I would suggest to put a ipdb breakpoint inside the callback taking as input the upload component, so that you can try inside the debugger to create a valid PIL object, inspect its content etc.

Hi @Emmanuelle, thanks for your reply. Yes indeed, function detect is accepting a PIL.Image object: https://github.com/akarazniewicz/smd/blob/master/models/detectors/maskrcnn.py. The other option would be to forward a string (or is it a path?). Maybe you know a way to forward a path string from an object that is saved only in RAM of the browser?
I will check your idea with the ipdb breakpoints out. Thank you very much.

@Emmanuelle I was able to solve the problem: If anyone is interested to know how to convert an uploaded image from base64 to a PIL Image object:

encoded_image = upload.split(",")[1]
decoded_image = base64.b64decode(encoded_image)
bytes_image = BytesIO(decoded_image)
image = Image.open(bytes_image).convert('RGB')

I think the crucial point is to take the second part of the base64 string (after the comma).