Converting matplotlib png to base64 for viewing in html template

Background

Hello, I am trying to make a simple web app, following a tutorial, that calculates a dampened vibration equation and returns a png of the result to the html page after it has been converted to a Base64 string.

Problem

The app functions normally except that when the result is calculated, a broken image icon is returned, likely because the Base64 string is not valid.

Troubleshooting

I have converted another png image to a Base64 string using an online converter and used <img src="data:image/png;base64, BASE64_STRING"/> to display the image successfully. I believe the template is appropriately formatted. I have also read other SO answers here and here and tried implementing those without success.

Relevant code

Here is where the image string is returned

from numpy import exp, cos, linspace
import matplotlib.pyplot as plt


def damped_vibrations(t, A, b, w):
    return A*exp(-b*t)*cos(w*t)


def compute(A, b, w, T, resolution=500):
    """Return filename of plot of the damped_vibration function."""
    t = linspace(0, T, resolution+1)
    u = damped_vibrations(t, A, b, w)
    plt.figure()  # needed to avoid adding curves in plot
    plt.plot(t, u)
    plt.title('A=%g, b=%g, w=%g' % (A, b, w))

    from io import BytesIO
    figfile = BytesIO()
    plt.savefig(figfile, format='png')
    figfile.seek(0)  # rewind to beginning of file
    import base64
    #figdata_png = base64.b64encode(figfile.read())
    figdata_png = base64.b64encode(figfile.getvalue())
    return figdata_png

Here is where the image is displayed

{% if result != None %}
<img src="data:image/png;base64,{{ result }}"\>
{% endif %}

If needed, I can provide the controller file as well. Thanks for any help!


Solution 1:

The beginning of the data in the template gives a clue to what's happening. &#39; is the HTML entity for a single quote '. Combined with the preceding b, b', it looks like the representation of a byte string, rather than the contents of the string.

Decode the byte string to a string before trying to render them with Jinja.

render_template('result.html', result=figdata_png.decode('utf8'))

Jinja renders the string representation of objects in {{ }}. The string representation of a byte string includes the b'' to distinguish it from a Unicode string. So you have to decode in order to display their value directly.