我正在开发一个生成多页(有时数百或数千页)PDF 文档以供打印的应用程序。每个页面都包含一个通用模板,上面叠加了一些特定于页面的内容(想想:自动填写纸质表格的“名称”字段)。
但是,问题是模板相当大(大约 100kb/页),并且在每一页上复制它会产生非常 大的 PDF 文件(目前 PDF 是使用 rsvg-convert 将充满 SVG 文件的目录转换为 PDF。
是否可以通过引用静态模板让每个PDF页面只包含自定义内容来减少重复?
理想情况下,我想知道如何使用 Python 或 Ghostscript 执行此操作,但我们将不胜感激。
请您参考如下方法:
您想要的是 PDF 文件中的 Form XObjects。来自 PDF 引用:
A form XObject is a PDF content stream that is a self-contained description of any sequence of graphics objects (including path objects, text objects, and sampled images). A form XObject may be painted multiple times—either on several pages or at several locations on the same page—and produces the same results each time, subject only to the graphics state at the time it is invoked. Not only is this shared definition economical to represent in the PDF file, but under suitable circumstances the PDF consumer application can optimize execution by caching the results of rendering the form XObject for repeated reuse.
许多应用程序添加,例如水印到 PDF 页面,将它们自动添加为 Form XObjects。例如,您可以使用 pdftk 将模板内容作为背景添加到已有页面特定内容的现有多页 PDF 中:
pdftk multipage.pdf background template.pdf output multipage+.pdf
使用 Ghostscript,您应该将模板作为 EPS,然后创建添加了 Form XObjects 的多页 PDF,然后使用其他一些方法添加页面特定的内容。但是,也许可以使用 “仅 Ghostscript” 实现一些聪明的方法,将特定页面叠加到具有背景的 PDF 中。要在每个页面上创建模板为 Form XObject 的“准备好填充”多页 PDF,请执行以下操作:
gs -sDEVICE=pdfwrite -o 100_pages_template.pdf \
-c '[/_objdef {background} /BBox [0 0 595 841] /BP pdfmark
save /showpage {} def
0 0 translate % adjust according to EPS BBox
(template.eps) run
restore
[/EP pdfmark
1 1 100 {
[{background} /SP pdfmark
showpage
} for'
不了解 Python,我认为它与使用 Perl 的下一个示例一样简单。在这里,我也创建了 100 页 PDF,每页都有模板:
use strict;
use warnings;
use PDF::API2;
my $pdf = PDF::API2->new();
my $tmpl = PDF::API2->open('template.pdf');
my $xo = $pdf->importPageIntoForm($tmpl, 1);
for (1..100) {
my $page = $pdf->page();
my $gfx = $page->gfx();
$gfx->formimage($xo, 0, 0);
# add page specific content
}
$pdf->saveas('out.pdf');
