pythonfirebaseimagegoogle-cloud-functionspython-imaging-library

Serving generated image from firebase


I'm working on a simple web app, using firebase.

Essentially I would like to make it so that whenever a user visits a page it will serve them an image with the text of the url:

For example mywebpage.com/happy_birthday/hannah.jpg, would serve the user a simple image takes an image I have stored in storage and writes the name 'hannah' across it.

I can easily modify the image with PIL, but I'm not sure how I can serve this to the user without having to pre-upload everything.

@https_fn.on_request(cors=options.CorsOptions(cors_origins="*", cors_methods=["get", "post"])):
def rss_image(req: https_fn.Request) -> https_fn.Response:
    return https_fn.Response(make_birthday_image(), mimetype='image/jpg')

from PIL import Image, ImageDraw

def make_birthday_image(name):
    image = Image.new('RGB', (100, 100), color='white')
    draw = ImageDraw.Draw(image)
    draw.text(name, font_size=10, fill='black')
    ... # unsure what to return here

Any advice would be super helpful!


Solution

  • You can use io.BytesIO to create file-like object in memory, save image in this object and send this object to browser. And if your function needs data instead of file-like object then you can get all data from object using .getvalue()

    You can see it in may questions how to server generated image in Flask without saving in file on disk.

    So you may need something like this

    from PIL import Image, ImageDraw
    import io
    
    def make_birthday_image(name):
        image = Image.new('RGB', (100, 100), color='white')
        draw = ImageDraw.Draw(image)
        draw.text(name, font_size=10, fill='black')
        ... # unsure what to return here
    
        obj = io.BytesIO()             # file in memory to save image without using disk  #
        image.save(obj, format='jpg')  # save in file (BytesIO)                           # https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save
        obj.seek(0)                    # move to beginning of file (BytesIO) to read it   #
        #obj = obj.getvalue()          # if you need data instead of file-like object
    
        return obj