pythonimagepyscriptpyodide

PyScript: Get image from API and display on webpage


this is my first question on SO. Please give me directions if the question is not clear.

I am trying to get an image from a public API and write it on a webpage using PyScript.

However, I am not able to get the image to display on the webpage. I tried different packages to read the image (PIL, matplotlib, imageio) and different methods to display the output (Setting "output" at the beginning of pyscript, using pyscript.write() ). Below you can find a full (non-working) example.

img is formatted as a Numpy array with uint8 values.

UPDATE: The data is obtained correctly from the API. If I treat the data as Numpy array I can see all the pixel values. However, I am not able to display the image on the webpage afterwards.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
        <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
        <py-env>
            - matplotlib
            - imageio
        </py-env>
    </head>
    <body>
        <h1>PyScript - images from API</h1>
        <div>
            <p>
                This webpage fetches a cat image from <a href="https://cataas.com/#/", target="_blank">cataas</a> and displays it below.
            </p>
        </div>
        <div id="image"></div>

    <py-script output="image">
from pyodide.http import pyfetch
import asyncio
from io import BytesIO
import matplotlib.pyplot as plt
import imageio.v3 as iio


response = await pyfetch(url="https://cataas.com/cat", method="GET")

img = iio.imread(BytesIO(await response.bytes()), index=None)

imgplot = plt.imshow(img)

imgplot
    </py-script>
    </body>
</html>

I tested on both Chrome and Firefox, but the image is never displayed.

Thanks in advance!


Solution

  • you need to assign the output image to some element in HTML document. Inside pyscript node add something like:

    document.querySelector("img").setAttribute("src", img)
    

    will display the image in tag: <img id ="img" src="src"> Use id="img" for .CSS

    And, I dont know how your code for downloading the images works but I googled a lot (dont remember the source, most likely this: https://www.jhanley.com/pyscript-loading-python-code-in-the-browser/) and created two functions:

    async def download(url):
                filename = Path(url).name
                response = await pyfetch(url)
                if response.status == 200:
                    status = response.status
                    with open(filename, mode="wb") as file:
                        file.write(await response.bytes())
                    return filename, status
                else:
                    status = response.status
                    filename = None
                    return filename, status
    
    async def process_response(url):
                response_content = await loop.run_until_complete(
                    download(url)
                    )
                if response_content[1] == 200:
                    data = base64.b64encode(open(response_content[0], "rb").read()).decode("utf-8")
                    src = f"data:image/png;base64,{data}"
                    return src
                else:
                    src = None
                    return src
    
    img = await process_response("url")
    document.querySelector("img").setAttribute("src", img)