将 matplotlib 图写入缓冲区,然后作为文件读取以将图像嵌入 PDF

2023-12-31

我正在尝试将几个 matplotlib 图形保存到使用 FPDF 创建的 PDF 中的特定位置。我不想将这些数字转储到文件中,然后将它们拉回。更好的解决方案似乎是将它们写入缓冲区,然后将它们读回,但我不确定这是否可能。

简化代码:

import pandas as pd
import matplotlib.pyplot as plt
from fpdf import FPDF
from io import BytesIO
import base64

# create figure
fig = plt.figure()

# add plot
ax = pd.Series( [1,3,2] ).plot()

# create bytesio object
bio = BytesIO()        

# save figure to bytesio
fig.savefig(bio, format="png", bbox_inches='tight')

# this works to save the figure to a file
with open("myfile.png", "wb") as file:
    file.write(bio.getvalue())

# create a PDF and set some attributes    
pdf = FPDF(orientation="L", unit="in", format="letter")
pdf.set_font('Arial', 'B', 14)
pdf.add_page()

# try to read the bytesio object as though it's a file
# pdf.image() expects a file name or a URL: https://pyfpdf.readthedocs.io/en/latest/reference/image/index.html
# trying to create a data url with the base64-encoded data inside it

pdf.image( name='data://image/png;base64,' + base64.b64encode(bio.getvalue()).decode() , x=1, y=1, w=3.5, type='png')

# save pdf
pdf.output("mypdf.pdf")

完整的堆栈跟踪:

---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-17-0ec65d0f583e> in <module>()
     30 # trying to create a data url with the base64-encoded data inside it
     31 
---> 32 pdf.image( name='data://image/png;base64,' + base64.b64encode(bio.getvalue()).decode() , x=1, y=1, w=3.5, type='png')
     33 
     34 # save pdf

~\AppData\Local\Continuum\anaconda3\lib\site-packages\fpdf\fpdf.py in wrapper(self, *args, **kwargs)
    148                 self.error("No page open, you need to call add_page() first")
    149             else:
--> 150                 return fn(self, *args, **kwargs)
    151         return wrapper
    152 

~\AppData\Local\Continuum\anaconda3\lib\site-packages\fpdf\fpdf.py in image(self, name, x, y, w, h, type, link)
    969                 info=self._parsejpg(name)
    970             elif(type=='png'):
--> 971                 info=self._parsepng(name)
    972             else:
    973                 #Allow for additional formats

~\AppData\Local\Continuum\anaconda3\lib\site-packages\fpdf\fpdf.py in _parsepng(self, name)
   1770                f = urlopen(name)
   1771         else:
-> 1772             f=open(name,'rb')
   1773         if(not f):
   1774             self.error("Can't open image file: "+name)

FileNotFoundError: [Errno 2] No such file or directory: 'data://image/png;base64,iVBORw0KGgoAAAANSU  #snipped for length#

由于 pdf.image() 可以采用 URL,因此我想构造一个实际上并不尝试打开文件的数据 URL。这就像在 HTML 页面中内嵌图像一样。就是这样的想法。我已经尝试了 getvalue() 、encode() 和decode() 的多次迭代,但没有得到正确的组合。

在本示例中,我成功写入文件以确保我的 BytesIO 对象中包含正确的数据,但将其转储到 pdf.image() 中不起作用。


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 matplotlib 图写入缓冲区,然后作为文件读取以将图像嵌入 PDF 的相关文章

随机推荐