5

I know this question has a few answers, but none satisfy me, because they all include Dash, and I want to use only basic plotly.

I have a local image file: /tmp/bla.svg (and also /tmp/bla.svg) which I want to appear as a logo on my graph:

This is my the graph code, working with an example from plotly:

    fig.add_layout_image(
        dict(
            source='https://raw.githubusercontent.com/cldougl/plot_images/add_r_img/vox.png',
            xref='paper', yref='paper',
            x=1, y=1.05,
            sizex=0.1, sizey=0.1,
            xanchor='center', yanchor='bottom'
        )
    )

This works well, but any attempt to change the source to a local image fails. The doc does not even give an option for a non-url image source.

I did try a local url - but failed:

source=r'file:///tmp/bla.png',

and also

source=r'file:///tmp/bla.svg',

I also tried using this answer - using base64 encoding:

def _get_image(path):
    with open(path, 'rb') as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode()
    encoded_img = f'data:image/png;base64,{encoded_string}'
    return encoded_img
...
source=_get_image(path)
...

but this also fails, even though I tested the output base64, and it is an image!

How can I make it work?

CIsForCookies
  • 12,097
  • 11
  • 59
  • 124
  • 1
    what's your environment? jupyter?, spyder?, vscode? – jayveesea Feb 12 '21 at 19:52
  • 1
    Don't see how that's connected. Nevertheless, I have a solution - I'll post it later. I eventually managed to use a base64 encoding of the svg file, and then take it as a url, no pillow :) – CIsForCookies Feb 13 '21 at 19:17
  • 1
    @CIsForCookies Any update on your solution? I am interested in applying it – KansaiRobot Feb 06 '22 at 06:44
  • 1
    @KansaiRobot I just read it once into a variable it then it worked. Guess I messed something there with decoding the image. My code looks now something like: `figure.add_layou_image(dict(source='data:image/svg+xml;base64,...', ...))`. Hope it helps – CIsForCookies Feb 06 '22 at 09:46

1 Answers1

11

For a local file you can use pillow (or similar) to read the file and then use that as the source for plotly.

from PIL import Image
pyLogo = Image.open("python-logo.png")

In my case I have python-logo.png in the same folder as my notebook.

Full example (adapted from here):

import plotly.graph_objects as go
import plotly.io as pio
from PIL import Image

# to render in jupyterlab
pio.renderers.default = "plotly_mimetype"

# Create figure
fig = go.Figure()

pyLogo = Image.open("python-logo.png")

# Add trace
fig.add_trace(
    go.Scatter(x=[0, 0.5, 1, 2, 2.2], y=[1.23, 2.5, 0.42, 3, 1])
)

fig.add_layout_image(
        dict(
            source=pyLogo,
            xref="x",
            yref="y",
            x=0,
            y=3,
            sizex=2,
            sizey=2,
            sizing="stretch",
            opacity=0.5,
            layer="below")
)

fig.show()
jayveesea
  • 2,886
  • 13
  • 25
  • I would like to ask what the code would look like if the inserted image were available on Google instead of in the local folder? I tried to do: source=https://logodownload.org/wp-content/uploads/2015/02/unesp-logo-11.png, but the image is not showing – Jane Borges Apr 25 '22 at 19:32
  • 1
    see [here](https://stackoverflow.com/questions/7391945/how-do-i-read-image-data-from-a-url-in-python) and use that method for `pyLogo` above – jayveesea Apr 25 '22 at 21:52
  • ...that said, it seems like the method [here](https://plotly.com/python/images/#add-a-background-image) should work directly, may need a new SO question, or some further research. – jayveesea Apr 25 '22 at 22:41
  • 1
    Your comment helped me to solve the problem. Includes answer in: https://stackoverflow.com/questions/71943523/how-to-add-a-google-image-to-a-chart-using-plotly-library Thank you! – Jane Borges Apr 27 '22 at 19:43
  • For the reference, installing PIL package may fail, as explained here: https://stackoverflow.com/questions/37311359/cant-install-pil. You may want to install pillow instead. – RandomCoder Dec 22 '22 at 15:43