In my Streamlit app, users can upload an image (JPG, JPEG, PNG), draw over it, and download that image. The app works perfectly on my local environment (localhost:8501), but when deployed to Streamlit Cloud, the original image does not appear as the background for the st_canvas component during the drawing step. However, the image displays correctly during the initial upload step.
You can find the project on GitHub here: GitHub - meghna-cse/cloakdocs-web-app: A Web App for Masking Information in Images
I explored the forum and tried several suggested approaches, but none resolved the issue. Below is a detailed summary of the approaches I’ve tried so far:
Approaches Tried that didn’t work:
-
Base64 Encoded String
Convert the uploaded image into a base64-encoded string and pass it to the background_image parameter of st_canvas. This led to an AttributeError because st_canvas expected an object with a height attribute, not a string.
Code:
buffered = io.BytesIO()
resized_image.save(buffered, format=“PNG”)
img_str = f"data:image/png;base64,{base64.b64encode(buffered.getvalue()).decode()}" -
Numpy Array
Tried converting the PIL image to a NumPy array and passed it to background_image. This resulted in a ValueError since the NumPy array wasn’t correctly interpreted by st_canvas.
Code:
img_array = np.array(original_image)
-
PIL Image Directly
Passed the uploaded image directly to the background_image parameter without reprocessing it. This approach worked locally but the image still didn’t appear as the canvas background on Streamlit Cloud.
Code:
background_image=resized_image,
-
In-Memory Image Handling
Tried to handle images entirely in memory using BytesIO to avoid file handling issues that might be causing the missing image. In the network tab, I noticed that requests for the image were blocked or missing (NS_BINDING_ABORTED). I suspected it might be a cross-origin resource sharing (CORS) issue or a Streamlit Cloud-specific restriction.
This fixed some issues with file handling, but the image still did not render on the st_canvas in Streamlit Cloud.Code:
def get_image_bytes(image: Image.Image) → BytesIO:
img_bytes = BytesIO()
image.save(img_bytes, format=‘PNG’)
img_bytes.seek(0)
return img_bytesAlso tried using the in-memory image (BytesIO) directly as the background image for st_canvas without reopening it, to avoid missing file issues. The image still didn’t render on Streamlit Cloud, though it worked locally.
-
Using Session
Stored the encoded and decoded images in Streamlit’s session_state to ensure they persisted across app reruns and were properly passed to the st_canvas component. This still did not solve the issue of the missing background image in Streamlit Cloud.
-
Downgraded streamlit_drawable_canvas to v0.9.0
I downgraded the version of the streamlit_drawable_canvas library to see if there was an issue introduced in newer versions. The image still didn’t render on Streamlit Cloud, though it worked locally.
If anyone has encountered a similar issue or can provide additional insights on handling images or working with streamlit_drawable_canvas on Streamlit Cloud, I would appreciate the help!
If any of the above approaches worked for you, I’d love to dig deeper into it and find a solution. Any insights would be greatly appreciated. Thank you in advance!