Converting matplotlib png to base64 for viewing in html template

13,393

The beginning of the data in the template gives a clue to what's happening. ' 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.

Share:
13,393

Related videos on Youtube

jclark754
Author by

jclark754

Updated on June 15, 2022

Comments

  • jclark754
    jclark754 almost 2 years

    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!

  • Darcy
    Darcy over 5 years
    For those wondering why this answer is downvoted, see the answer by @Martijn Pieters here