我正在使用matplotlib来生成PDF数据。然而,即使是最简单的数字也会产生相对较大的文件,下面的MWE生成一个几乎1MB的文件。我已经意识到,较大的文件大小是由于matplotlib完全嵌入了所有使用过的字体。由于我要制作相当多的情节,并希望缩小文件大小,所以我想知道:
主要问题:
是否有办法使matplotlib嵌入字体子集而不是完整的字体?我也会很好,不包括字体在所有。
到目前为止考虑的问题:
由于使用外部软件生成带有嵌入式子集的文件很容易,尽管劳动强度很大,那么在matplotlib中是否有可能直接实现这一点呢?任何帮助都将不胜感激。
MWE
import matplotlib.pyplot as plt #Setup
import matplotlib as mpl
mpl.rcParams['pdf.fonttype'] = 42
mpl.rcParams['mathtext.fontset'] = 'dejavuserif'
mpl.rc('font',family='Arial',size=12)
fig,ax=plt.subplots(figsize=(2,2)) #Create a figure containing some text
ax.semilogy(1,1,'s',label='Text\n$M_\mathrm{ath}$')
ax.legend()
fig.tight_layout()
fig.savefig('test.pdf')
环境: matplotlib 3.1.1
发布于 2020-02-10 07:07:10
把这个留在这里,以防其他人在寻找类似的东西:毕竟,我决定选择Ghostscript。由于额外的步骤,这并不完全是我想要的,但至少它可以自动化:
import subprocess
def gs_opt(filename):
filenameTmp = filename.split('.')[-2]+'_tmp.pdf'
gs = ['gswin64',
'-sDEVICE=pdfwrite',
'-dEmbedAllFonts=false',
'-dSubsetFonts=true', # Create font subsets (default)
'-dPDFSETTINGS=/prepress', # Image resolution
'-dDetectDuplicateImages=true', # Embeds images used multiple times only once
'-dCompressFonts=true', # Compress fonts in the output (default)
'-dNOPAUSE', # No pause after each image
'-dQUIET', # Suppress output
'-dBATCH', # Automatically exit
'-sOutputFile='+filenameTmp, # Save to temporary output
filename] # Input file
subprocess.run(gs) # Create temporary file
subprocess.run(['del', filename],shell=True) # Delete input file
subprocess.run(['ren',filenameTmp,filename],shell=True) # Rename temporary to input file
然后打电话
filename = 'test.pdf'
plt.savefig(filename)
gs_opt(filename)
这将将图形保存为test.pdf,使用Ghostscript创建临时优化的test_tmp.pdf,删除初始文件并将优化文件重命名为test.pdf。
与使用矢量图形编辑器导出文件相比,Ghostscript生成的PDF仍然要大几倍(通常是4-5倍)。但是,它正在将文件大小减少到初始文件的1/5至1/10之间。这是件事。
发布于 2020-12-18 23:02:50
PGF后端有助于显着地减少PDF文件的大小。只需将mpl.use('pgf')
添加到代码中即可。在我的环境中,这一修正导致了以下情况:
但是,对于实际数字,执行时间通常会随着文件大小的增加而减少。
PDF大小的减少是由于嵌入了字体子集。
$ pdffonts pdf_backend.pdf
name type emb sub uni prob object ID
---------------------------- ----------------- --- --- --- ---- ---------
ArialMT CID TrueType yes no yes 14 0
DejaVuSerif-Italic CID TrueType yes no yes 23 0
DejaVuSerif CID TrueType yes no yes 32 0
$ pdffonts pgf_backend.pdf
name type emb sub uni prob object ID
---------------------------- ----------------- --- --- --- ---- ---------
KECVVY+ArialMT CID TrueType yes yes yes 7 0
EFAAMX+CMR12 Type 1C yes yes yes 8 0
EHYQVR+CMSY8 Type 1C yes yes yes 9 0
UVNOSL+CMR8 Type 1C yes yes yes 10 0
FDPQQI+CMMI12 Type 1C yes yes yes 11 0
DGIYWD+DejaVuSerif CID TrueType yes yes yes 13 0
另一种选择是生成一个EPS文件(使用PostScript后端)并将其转换为PDF格式,例如通过epstopdf
(使用GhostScript解释器)。这种方法将PDF文件减少到9K。然而,值得注意的是,PS后端不支持透明度。
https://stackoverflow.com/questions/60076026
复制相似问题