20

Is there a way to use PIL with matplotlib to place logos that are in EPS or SVG (or any scalable vector format) in order to place the logo on the graph and output the final file as EPS. Now I get a terribly rendered graphic because there is an .png file trying to be converted to EPS format, where the goal is to save the image as an .eps or .svg.

I think this may be a restriction due to the backend, I'm open to changing which one I use.

This is what does not work:

    ax1.set_axis_bgcolor('#fafafa')
    
    img = image.imread('./static/images/logo.png')
    image_axis = fig.add_axes(ax1.get_position())
    image_axis.patch.set_visible(False)
    image_axis.yaxis.set_visible(False)
    image_axis.xaxis.set_visible(False)
    image_axis.set_xlim(0,19.995)
    image_axis.set_ylim(0,11.25)

    image_axis.imshow(img, extent=(11.79705,18.99525,.238125,1.313625), zorder=-1, alpha=0.15) #need to keep a 5.023 x by y ratio (.4 x .079)

    fig.savefig('static/images/graphs/'+filename+'.eps', format='eps', bbox_inches='tight')

Any updates?

Aviv Yaniv
  • 6,188
  • 3
  • 7
  • 22
Jared
  • 3,651
  • 11
  • 39
  • 64
  • Have you just tried it? [The docs](http://matplotlib.org/1.3.1/users/image_tutorial.html#importing-image-data-into-numpy-arrays) imply that if the image passed to `imshow` is non-png, matplotlib will fall back on PIL which should be able to cope with eps ([docs](http://pillow.readthedocs.org/en/latest/handbook/image-file-formats.html#eps)). I haven't got any eps files to hand to test, but could try tomorrow, potentially. – J Richard Snape Sep 18 '15 at 23:18

3 Answers3

2

This is an old question, but worth answering for current and future visitors wanting to do the same.

There is a way to load SVG files and convert them into Path objects, implemented in the svgpath2mpl package. From the project's page:

A path in SVG is defined by a 'path' element which contains a d="(path data)" attribute that contains moveto, line, curve (both cubic and quadratic Béziers), arc and closepath instructions. Matplotlib actually supports all of these instructions natively but doesn't provide a parser or fully compatible API.

Seen at Matplotlib custom marker/symbol.

wagnifico
  • 632
  • 3
  • 13
0

I usually achive a better rendering in this case with something like:

from PIL import Image

logo = Image.open('icons\logo.png')
# TODO define bbox as a matplotlib.transforms.Bbox
image_axis.imshow(logo, clip_box=bbox, aspect='equal',
   origin='lower', interpolation='nearest')

(Matplotlib 1.4.2, if you use an old version playing with interpolation and origin options may help)

GBy
  • 1,719
  • 13
  • 19
  • Does this work with vector graphics -- as opposed to pngs? – Jared Sep 21 '15 at 13:15
  • PIL can handle .eps files http://pillow.readthedocs.org/en/latest/handbook/image-file-formats.html they will be rasterized but you can control the number of dots (see the link) – GBy Sep 21 '15 at 19:35
  • The goal is for the figure to save as an eps or some other scalable vector graphic, with the logo included. – Jared Sep 22 '15 at 00:33
  • Ok. With this code, you can save the figure as pdf (probably eps also, not tested), with the logo included - but it will be embedded as a raster image. – GBy Sep 22 '15 at 04:44
0

I removed my code snippet as it was not useful.

It is not possible to use native SVG as image in Matplotlib. Matplotlib supports natively only png and then falls back to Pillow which does not support svg either, see http://pillow.readthedocs.io/en/latest/handbook/image-file-formats.html or matplotlib image documentation.

Pillow supports eps, so that will work! (I am not sure what matplotlib will make of it internally)

I use it like this :

# Pillow must be there
import matplotlib.image as mpimg

def Save_svg(fig):
    # expects a matplotlib figure
    # And puts a logo into a frameless new axes
    imagefile = 'logo.eps'
    svgfile   = 'output.svg'
    logoax    = [0.265, 0.125, 0.3, 0.3]
    img=mpimg.imread(imagefile)
    #
    newax = fig.add_axes(logoax, anchor='SW', zorder=100)
    newax.imshow(img)
    newax.axis('off')
    #
    fig.savefig(svgfile,dpi=300)
JRM
  • 185
  • 2
  • 9
  • 1
    Your example embeds a jpg logo - OP wants to embed eps/svg I think. I think the point is that they want to keep in vector graphics throughout. – J Richard Snape Feb 02 '16 at 22:41
  • @JRichardSnape That's correct - the goal is to have the output in SVG/EPS. I still haven't solved this, but will update if I do. – Jared Feb 02 '16 at 23:23
  • I have solved it recently, so I renewed my answer above completely – JRM Mar 29 '18 at 09:27