我有一个从SVG文件创建的图表,并使用cairosvg库加载。
我想通过直接matplotlib命令以编程方式定义额外的重叠图来进一步增强此图。
我正在尝试在内存中执行此操作而不写出文件并重新加载。仅保存最终文件。
但是,将现有的cairo与matplotlib渲染的cairo 组合起来很难实现。我认为this was a potential solution,但不确定。
简化示例:
import matplotlib
matplotlib.use('Cairo') # Make sure here that our figures will use Cairo!
from cairosvg import surface
from cairosvg import parser
import matplotlib.pyplot as plt
import matplotlib.image as img
import numpy as np
SVG='\
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">\
<rect id="arena" x="10" y="10" width="480" height="480" fill="#ff5555" fill-opacity="0.5"/>\
</svg>\
'
svg = parser.Tree(bytestring=SVG)
surf = surface.PNGSurface(svg,None,1)
#surf.cairo.write_to_png("test-svg.png") # Can do this to see svg render to file
surf.finish() # Required?
ctx = surf.context # Can get the context here fine..
fig = plt.imshow(ctx) # <----- MAGIC REQUIRED HERE ABOUTS
#fig = plt.figure() # This works like a normal plot - but no svg
ax = fig.gca() # Create some overlay data
x = np.array(np.random.randn(100))
y = np.array(np.random.randn(100))
ax.plot(x,y)
plt.savefig("test-final.png") # Save svg & overlay plot
编辑:也在尝试以下内容,基于前面的链接。尽管如此,仍然没有快乐。
from matplotlib.artist import Artist
class SurfArtist(Artist):
def __init__(self,surf):
Artist.__init__(self)
self._surf = surf
def draw(self,renderer):
from matplotlib.backends.backend_cairo import RendererCairo
if not isinstance(renderer, RendererCairo):
raise TypeError("backend not supported")
ctx = renderer.gc.ctx if hasattr(renderer, "gc") else renderer.ctx
self._surf.context = ctx
self._surf.cairo.show_page()
...
fig = plt.figure()
ax = fig.gca()
surf_artist = SurfArtist(surf)
surf_artist.set_zorder(float('inf'))
ax.artists.append(surf_artist)
答案 0 :(得分:0)
下面的代码应该可以正常工作,首先将表面转换为numpy数组,如https://github.com/Kozea/CairoSVG/issues/57
matplotlib.use('Cairo') # Make sure here that our figures will use Cairo!
from cairosvg import surface
from cairosvg import parser
import matplotlib.pyplot as plt
import matplotlib.image as img
import numpy as np
# function to convert to array
def surface_to_npim(surface):
""" Transforms a Cairo surface into a numpy array. """
im = +np.frombuffer(surface.get_data(), np.uint8)
H,W = surface.get_height(), surface.get_width()
im.shape = (H,W, 4) # for RGBA
return im[:,:,:3]
SVG='\
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="500" height="500">\
<rect id="arena" x="10" y="10" width="480" height="480" fill="#ff5555" fill-opacity="0.5"/>\
</svg>\
'
svg = parser.Tree(bytestring=SVG)
surf = surface.PNGSurface(svg,None,1)
#surf.cairo.write_to_png("test-svg.png") # Can do this to see svg render to file
surf.finish() # Required?
# convert svg and plot
img = surface_to_npim(surf.cairo)
plt.imshow(img)
# Create some overlay data
x = np.array(np.random.randn(100))
y = np.array(np.random.randn(100))
plt.plot(x,y)
plt.savefig("test-final.png") # Save svg & overlay plot