将SVG转换为PDF(svglib + reportlab不够好)

12

我正在批量创建一些SVG并需要将其转换为PDF文档进行打印。 我一直在尝试使用svglib及其svg2rlg方法,但我刚刚发现它对于保留我的文档中的矢量图形实在太糟糕了,它几乎无法正确定位文本。

我动态生成的SVG格式良好,并已经测试过svglib是否存在问题。

那么除了svglib和ReportLab之外,我还有哪些选择? 它必须是免费或非常便宜,因为我们的项目预算已经用完了。 我们负担不起ReportLab Plus每年1k美元的费用。

我正在使用Python,但在这个阶段,只要它能在我们的Ubuntu服务器上运行就好。

编辑:测试了Prince。更好,但仍然忽略了文件的一半。


你能否使用以下两种方法的组合:https://dev59.com/omw15IYBdhLWcg3weLoF#6599172 和 http://www.blog.pythonlibrary.org/2012/01/07/reportlab-converting-hundreds-of-images-into-pdfs/ 后者使用了reportlab,但我想知道在生成pdf时是否可以不使用Plus版本。你可能可以直接使用Cairo生成pdf,但我不能确定,因此只能留下评论而不是答案。 - sgallen
4个回答

9

我使用inkscape进行此操作。在您的Django视图中执行以下操作:

from subprocess import Popen

x = Popen(['/usr/bin/inkscape', your_svg_input, \
    '--export-pdf=%s' % your_pdf_output])
try:
    waitForResponse(x)
except OSError, e:
    return False

def waitForResponse(x): 
    out, err = x.communicate() 
    if x.returncode < 0: 
        r = "Popen returncode: " + str(x.returncode) 
        raise OSError(r)

如果您的文本在.pdf输出中未正确显示,请记住,您可能需要将在.svg中引用的所有字体文件作为参数传递给inkscape。


Inkscape对字体的处理良好吗?在Windows环境中安装的字体能否被Inkscape识别? - Shmack
@ShanerM13 Inkscape对字体处理得很好。我没有在Windows上使用过Inkscape,但对于你的第二个问题,答案似乎是是的,如果正确安装的话 - ram1

3

CairoSVG 是我正在使用的工具:

import cairosvg
cairosvg.svg2pdf(url='image.svg', write_to='image.pdf')

现在已经测试过了,但不幸的是它在渲染我的SVG方面仍然很弱。 - Oli
你确定你的SVG格式正确吗?Cairo的渲染非常稳定。此外,我正在使用WeasyPrint来生成PDF,尽管它还有一些不完善之处,但在限制条件下仍然可以正常工作。 - plaes

1

rst2pdf使用reportlab生成PDF。它可以使用inkscape和pdfrw读取PDF。

pdfrw本身有一些示例,展示了如何读取PDF并使用reportlab输出。

回应下面Martin的评论(我可以编辑此答案,但没有声望在其评论上发表评论...):

reportlab对SVG文件一无所知。一些工具(例如svg2rlg)尝试通过将它们绘制到reportlab画布中来重新创建SVG图像为PDF。但是,您可以通过另一种方式使用pdfrw进行操作-如果您可以使用另一个工具将SVG文件转换为PDF图像,则pdfrw可以将该转换后的PDF作为表单XObject添加到您使用reportlab生成的PDF中。就reportlab而言,这与放置JPEG图像没有什么区别。

某些工具会对SVG文件进行可怕的处理(例如将它们光栅化)。据我的经验,inkscape通常做得很好,并以矢量格式保留它们。您甚至可以无头地执行此操作,例如“inkscape my.svg -A my.pdf”。

我写 pdfrw 的初衷就是为了这个确切的用例——能够在 reportlab 创建的新 PDF 中重复使用矢量图像。

这如何解决OP的问题?我相信他不想使用reportlab,因为它的SVG处理质量不够好。 - Martijn Pieters

0

只是想让你知道,为了未来的问题,我找到了解决这个问题的方法:

# I only install svg2rlg, not svglib (svg2rlg is inside svglib as well) 
import svg2rlg

# Import of the canvas
from reportlab.pdfgen import canvas

# Import of the renderer (image part)
from reportlab.graphics import renderPDF

rlg = svg2rlg.svg2rlg("your_img.svg")
c = canvas.Canvas("example.pdf")
c.setTitle("my_title_we_dont_care")

# Generation of the first page
# You have a last option on this function, 
# about the boundary but you can leave it as default.
renderPDF.draw(rlg, c, 80, 740 - rlg.height)
renderPDF.draw(rlg, c, 60, 540 - rlg.height)
c.showPage()

# Generation of the second page
renderPDF.draw(rlg, c, 50, 740 - rlg.height)
c.showPage()

# Save
c.save()

在位置(80,740-h)上稍微调整一下,这只是位置而已。

如果代码无法正常工作,您可以查看render的reportlab库报告。 您可以在reportlab中使用一个函数直接从图像创建pdf:

renderPDF.drawToFile(rlg, "example.pdf", "title")

你可以打开并阅读它。它不是很复杂。这段代码来自这个函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接