PDF 使用 PHP + GhostScript 裁剪偶数页

PDF crop even-odd pages with PHP + GhostScript

我正在处理裁剪 PDF 并将其导入 PDF 模板的例程。我正在使用 GhostScript,从 PHP 脚本和 FPDI 使用 exec() 调用。所有 运行 服务器端。

到目前为止,我可以使用 this post(设置 CropBox)中解释的步骤使用 GhostScript 裁剪 pdf 文档。

下一步是以不同方式裁剪文档的偶数页和奇数页。所以我尝试了 SuperUser 站点中 this other post 中解释的方法,将自定义 PostScript 代码传递到 -c 参数到 GhostScript:

-c "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def 
CurrPageNum 2 mod 1 eq {28 0 translate} {} ifelse } bind  >> setpagedevice"

此方法将奇数页移动 28 pt,对偶数页执行 none。因此,我尝试修改它,传递 CropBox(es)(%s 占位符在 sprintf 句子中替换为适当的坐标):

-c "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def 
CurrPageNum 2 mod 1 eq {[/CropBox [%s %s %s %s]} {[/CropBox [%s %s %s %s]} 
ifelse } bind  >> setpagedevice"

这是对 4 页 pdf 文件执行的完整命令:

"C:\Program Files (x86)\gs\gs9.07\bin\gswin32c.exe" -sDEVICE=pdfwrite 
-o C:\inetpub\wwwroot\ledrail\tmp\output.pdf 
-c "<< /CurrPageNum 1 def /Install { /CurrPageNum CurrPageNum 1 add def 
CurrPageNum 2 mod 1 eq {[/CropBox [119.04 168.336 505.92 715.428]}
{[/CropBox [59.52 84.168 505.92 715.428]} ifelse } bind >> setpagedevice"
-f C:\inetpub\wwwroot\ledrail\documentacio\pdf\documentacio_15.pdf

显然,我得到一个错误,因为 [/CropBox... 是无效的 PS 代码。

Error: /typecheck in --.postinstall--

编辑以澄清:

所以,我的问题是:我如何传递 相当于 两个 CropBox(es) - 对于奇数页和偶数页 -上面显示的 PostScript 代码?或者,还有另一种方法可以通过命令行 with GhostScript 实现此目的?

显然,我知道 CropBox 不是 PostScript 有效代码,但有什么替代方案?

您不能在 PostScript 中设置 'CropBox',因为 CropBox 不是 PostScript 语言的一部分,它是特定于 PDF 的。

您需要发送带有 /CropBox 的 /PAGE pdfmark,正如您引用的第一个 post 所说。您没有设置 /Install。

GhostScript 可以处理在命令行通过-c 参数传递的PostScript 文件和PostScript 命令。因此,为了实现不平凡的事情,您至少应该了解这门语言的基础知识。

从来源获取相关文档:PostScript Language Reference Manual, 3rd ed. and the PostScript Language Tutorial and Cookbook 如果您一生中没有见过 PostScript(就像我的情况一样)。

KenS指点我:

You need a /EndPage procedure (which does get passed to setpagedevice) and that procedure needs to call the pdfmark.

文档指出 EndPage

A procedure to be executed at the end of each page. Before calling the procedure, the interpreter pushes two integers on the operand stack—a count of previous showpage executions for this device and a reason code indicating the circumstances under which this call is being made:

0 - During showpage or (LanguageLevel 3) copypage

1 - During copypage (LanguageLevel 2 only)

2 - At device deactivation

The procedure must return a boolean value specifying whether to transmit the page image to the physical output device.

因此,这段代码(来自 KenS 的 previous answer

<</EndPage {0 eq {[/CropBox [0 0 612 792] /PAGE pdfmark true}{false}ifelse}>> setpagedevice

为当前页面传递 CropBox - 指定坐标 - 每次调用 EndPage 时原因为 0(显示页面)且 returns 为真。否则,什么都不做并且 returns 错误。这个原因码是操作数栈中的第一项,在操作0 eq {true block}{false block} ifelse中“消耗”后(等于0?),栈中就没有了.

因此,堆栈中的下一个值是已处理的页数。我们在上面显示的 true 部分代码中用另一个 ifelse 扩展代码:

{2 mod 0 eq {[/CropBox [0 0 612 792] /PAGE pdfmark true} 
{[/CropBox [50 0 612 792] /PAGE pdfmark true} ifelse}

这会在当前页面(位于堆栈顶部)和 2 之间执行取模,然后测试是否等于 0(即测试 odd/even 页面)。如果偶数(模数 = 0)通过第一个 CropBox,否则第二个,并且 returns 在这两种情况下都为真。

所以,完整的 PostScript 代码:

"<</EndPage {0 eq {2 mod 0 eq {[/CropBox [0 0 612 792] /PAGE pdfmark true}
{[/CropBox [50 0 612 792] /PAGE pdfmark true} ifelse}{false}ifelse}>> setpagedevice"

当作为 -c 参数传入 GhostScript 时,允许我们以不同方式裁剪 PDF 文档的偶数页和奇数页,即如果我们想抑制额外的 space 用于绑定原始文件。