Displaying Imagen images in web applications
In addition to generating text, many LLMs can generate images. Of course they’re fun to look at and share, but you can also use them to personalize web pages and show your product in a variety of worlds the customer creates. We’re only starting to see all the possible uses of generated images.
It’s easy to get started with Imagen, Google’s text-to-image model. There’s a link on that page that lets you try out Imagen in your browser. If you’re interested in seeing code for image generation, a quick start is available in this notebook. Displaying an image named myImage in a notebook is as easy as myImage.show() .
Encouraged by this, you may be ready to add Imagen to a web application immediately. More good news–there’s a Codelab that walks you through the steps to do this. And if you’re familiar with deploying to Cloud Run and using Flask, most of that lab shouldn’t be too hard. (And if you’re not familiar with them, it’s a great way to learn more.) Creating an image comes down to creating a model, asking it to generate an image given a prompt, and showing the image:
generation_model = ImageGenerationModel.from_pretrained("imagegeneration@006")
responses = generation_model.generate_images(
prompt="A watercolor painting of autumn leaves falling in the wind",
)[0]
response.show()
But then reality strikes. When you go to use the show() method that worked so smoothly in a notebook, it doesn’t work. And sure enough, the documentation for the GeneratedImage makes that clear:
So, we need to find an alternative to show that will work in a non-notebook environment. Fortunately, we have a lot of possibilities. Let’s explore them.
Our constraints
Besides creating an image that will displayed, what other constraints do we have? Some possible requirements are:
- Allow multiple users to use the application simultaneously.
- This means that when we create an image, we won’t just be able to save it to a file with a fixed name, since many if there are multiple users, they would all want to use that name. Who knows which image they’d get?
- Provide for user privacy.
- If someone is using the app to look at potential designs for a the next great water bottle, we don’t want someone else to be able to retrieve that image accidentally.
- Reduce storage needs.
- You could create keys for each user and store their images with that key as part of the image name, but this may take up a lot of space in your app’s storage.
- The image needs to be converted to a form that can be displayed by the HTML command:
<img src="{{image_uri}}">. So we’ll need to have a URL for the image.
In short, we need a way to store a user image so it is accessible only to the user who requests it, but we don’t want to store user images. Sounds tricky.
But it can be done!
Data URL to the rescue
There is a less common, though still completely standard, way to make this work. Instead of giving the img tag a URL that needs to be fetched from some server, give it a URL that contains the entire image itself. Doing that requires using a data URL.
Instead of passing a location, data URLs send all of the data in the URL. An example is below (from [1]):
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAIAAAC0Ujn1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEDSURBVEhLtZJBEoMwDAP7lr6nn+0LqUGChsVOwoGdvTSSNRz6Wh7jxvT7+wn9Y4LZae0e+rXLeBqjh45rBtOYgy4V9KYxlOpqRjmNiY4+uJBP41gOI5BM40w620AknTVwGgfSWQMK0tnOaRpV6ewCatLZxn8aJemsAGXp7JhGLBX1wYlUtE4jkIpnwKGM9xeepG7mwblMpl2/CUbCJ7+6CnQzAw5lvD/8DxGIpbMClKWzdjpASTq7gJp0tnGaDlCVzhpQkM52OB3gQDrbQCSdNSTTAc7kMAL5dIDjjj64UE4HmEh1NaM3HWAIulQwmA4wd+i4ZjwdYDR00GqWsyPrizLD76QCPOHqP2cAAAAAElFTkSuQmCC
The beginning indicates this URL holds data originally in the format image/png and base 64 encoded in the remainder of the URL. This encodes the icon .
Yes, most modern browsers can handle very long URLs. So, instead of having to store the image and send its URL, with the privacy and space issues this may lead to, we’ll generate an image and then convert it to Base64 and send it directly to the function that will render the WWW page.
Using the Data URL
There are still complications that we’ll have to deal with. When you examine the the documentation for the GeneratedImage, the only method that looks useful is save :
This requires a location to save the image to. Which sounds like we’re back to our original problem, but it turns out, Python has us covered in this case. The tempfile library provides the ability to create a variety of temporary files and directories, including the NamedTemporaryFile. We can use the name of that temporary file with the GeneratedImages’s save as shown below:
with tempfile.NamedTemporaryFile("wb") as f:
filename = f.name
response.save(filename, include_generation_parameters=False)
# process the saved file here, before it goes away
The generated image is saved to the temporary file. We don’t care what the name is, just that it has a unique name. Now we can create the Base64 encoding so we can send the image to the template to be displayed. To do this, we’ll need to:
- open the file we just wrote
with open(filename, "rb") as image_file: - read it in
binary_image = image_file.read() - get its Base64 encoding
base64_image = base64.b64encode(binary_image).decode("utf-8") - create the data URL holding this encoding:
image_url = f"data:image/png;base64,{base64_image}"
Since all of this will be included in the with statement, the temporary file will be closed and automatically cleaned up when this is done. The final code to get a data URL (image_url) from a generated image (response) is:
with tempfile.NamedTemporaryFile("wb") as f:
filename = f.name
response.save(filename, include_generation_parameters=False)
# process the saved file here, before it goes away
with open(filename, "rb") as image_file:
binary_image = image_file.read()
base64_image = base64.b64encode(binary_image).decode("utf-8")
image_url = f"data:image/png;base64,{base64_image}"
The final step is to render an HTML template that will display the image in image_url.
And that’s it
At least for being able to get a URL from a generated image. If you want to go through all the steps to create a web app to get a prompt from a user and display the image generated for the prompt, take a look at this Codelab.
I look forward to seeing how you can use this ability in your apps![1]https://www.learningtree.com/blog/encoding-image-css-html/, Retrieved 4 November 2024.
