Transform 'LazyMedia' object to (PIL) image

Hi y’all,

I’ve connected my app to some existing code on my local pc (Uplink). What I’m trying to do is using an uploaded image in my app on my code. However, I’ve stored the uploaded file in a table and then push this table over to my local existing code.

The problem I’ve got is that it pushes the ‘LazyMedia’ object. I want to transform this object to an actual image (preferrably PIL) without actually storing this image on my local computer.

Any tips?

This is how my server side code looks like now, but it returns an AttributeError: ‘LazyMedia’ object has no attribute ‘size’. Which is logical ofcourse.

Code Sample:

@anvil.server.callable
def get_thumbnail_images(file):
    # Python class is setup
    IMT = ImageTransformer(name=file.name, input_image=file)
    # The images are transformed in IMT._RUN() 
    IMT._RUN()
    # Object from my class returns a list of images
    thumbnail_images = IMT.images
    return thumbnail_images

If you look at the docs for media objects, you’ll see there’s a get_bytes() method (or something like that, going from memory). You can use that to fetch the contents of the media object as a byte string. You’ll then have to see how to pass that byte string to whatever you’re trying to construct.

2 Likes

I’m pretty sure PIL will take a file like object (which you can create in such a way as to keep the image in memory like you require).

Something Like:

import io

file_obj = io.BytesIO( lazymedia_object.get_bytes() )
PIL_image_obj = PIL.Image.open( file_obj )

Here’s a link where we did something similar with pandas:

1 Like

Quick follow-up question. What is exactly the procedure when I’m having the transformed PIL images but I want to feed them back to my app.

My initial thoughts was to transform these with anvil.BlobMedia, but setting the self.image.source = that object does not work (it doesn’t give an error, but also does not display anything).

Code Sample:

@anvil.server.callable
def get_thumbnail_images(file):
    # Python class is setup
    IMT = ImageTransformer(name=file.name, input_image=file)
    # The images are transformed in IMT._RUN() 
    IMT._RUN()
    # Object from my class returns a list of images
    thumbnail_images = IMT.images
    
    names = ['1', '2', '3']
    return [anvil.BlobMedia(content_type="image/png", content=image.tobytes(), name=name[idx]) for name, image in enumerate(thumbnail_images)]

I think you mean this to be:

    return [ anvil.BlobMedia(content_type="image/png",
      content=image.tobytes(),
      name=names[idx] )
      for idx, image in enumerate(thumbnail_images) ]

If image.tobytes() produces a bytes string of an actual .png file it should work, so maybe take one of them and dump it out to a file like:

with open("test.png", "wb") as f:
  f.write(thumbnail_images[0].tobytes())

… and see if that image can be viewed as a png.

If so, then try it out in an image component and see how far you get:

If you get that far and still have questions you should probably start a new question on the forum, since this one is marked as solved.