如何解决在 PDF 文件上叠加一个 PS 文件
我发现有人回答了类似的问题 Overlay two postscript files (command line approach)?,但是,该解决方案对我不起作用,而且我的要求有点不同(我的一个文件是多页文件)
我有一个不受我控制的 PDF 文件 (DrawingSheet.pdf
)。我有一个 PostScript 文件 (Table.ps
),我通过使用 XSLFO 和 Apache FOP 转换 XML 文件来生成它。 Table.ps
包含一张表。
DrawingSheet.pdf
有多个页面。 Table.ps
只有一页。 DrawingSheet.pdf
和 Table.ps
都具有相同的纸张尺寸 - A 尺寸,横向。我想将该表从 Table.ps
放在 DrawingSheet.pdf
的最后一页的顶部。我不想在 DrawingSheet.pdf
的末尾“附加”表格页面作为附加页面。我正在使用命令行 GhostScript (v9.27)。
根据那篇文章的建议,我写了以下 Overlay.ps 文件:
/origshowpage /showpage load def
/showpage {} def
gsave
(DrawingSheet.pdf) run
grestore
(Table.ps) run
origshowpage
那行不通。我得到的是表格页面“附加”到 DrawingSheet.pdf
而不是覆盖在最后一页的顶部。
我做错了什么?我怎样才能实现我想要的?
已编辑-1:
如果两个文件中的页数相同以简化逻辑有帮助,那么我可以生成 Table.ps
以与 DrawingSheet.pdf
文件的页数相同,并且表格只出现在最后一个Table.ps
的页面。
已编辑-2:
或者,我尝试了以下方法(类似于将图像水印添加到 PDF 文件)。这样做的最终结果是我的空白页与 DrawingSheet.pdf
中的页数一样多。有趣的是,当我加载生成的空白 PDF 时,我可以看到 Acrobat Reader 在屏幕上闪烁表格,但是当加载整个文件时,我最终看到的只是空白页。
对解决此问题的任何帮助非常感谢。
<<
/EndPage
{
2 eq
{
pop false
}
{
gsave
1 dict begin
/showpage {} def
(Table.ps) run
end
grestore
pop true
} ifelse
} bind
>> setpagedevice
Edited-2 - 附加说明:如果我从上面的代码中注释掉 gsave
和 grestore
,那么我不会得到空白页,而是现在每一页都是用 Table.ps
中的表格“替换”(无重叠)。
Edited-3 - 部分成功:
在看到这篇文章后:Edit (every page of a) Postscript file manually,我尝试了这种方法。我将 DrawingSheet.pdf
转换为 DrawingSheet.ps
,确定最后一个 %%EndPageSetup
行,并在该行之后插入以下代码:
% BUNCH OF LInes NOT SHOWN %
%%BeginPageSetup
4 0 obj
<</Type/Page/MediaBox [0 0 792 612]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
/Font 10 0 R
>>
/Contents 5 0 R
/CropBox
[0 0 792.0 612.0]
/BleedBox
[0 0 792.0 612.0]
/TrimBox
[0 0 792.0 612.0]
>>
endobj
%%EndPageSetup
%gsave % <== My Edits
1 dict begin % <== My Edits
/showpage {} def % <== My Edits
(Table.ps) run % <== My Edits
end % <== My Edits
%grestore % <== My Edits
5 0 obj
<</Length 30050>>stream
% BUNCH OF LInes NOT SHOWN %
通过此编辑(gsave 和 grestore 注释掉 - 如果我取消注释它们,则这不起作用),我将我的表格强加在最后一页。表格看起来不错,但是 pdf 的原始最后一页在叠加后显示为在 X 轴的中心上翻转。页面截图为:
你能读到的文字来自Table.ps
,翻页的文字是DrawingSheet.pdf
最后一页的原文(当然原pdf的那一页没有翻页) .
不确定我做错了什么来获得翻转的图像?
已编辑-4:
为“Edited-2”添加了额外的注释
解决方法
我尝试了您的 endpage,终于让这种方法奏效了。 EndPage 将原因代码 0 或 1 和页面计数放在堆栈上(对于某些 pdf 来说不可靠),因此替代方法是 /PageCount 变量,我同时显示两者。这些计算页数并在页尾递增。
在页面完成之前,您需要知道在页面上放置叠加层的页数。 “finalpage”变量也可以在 ghostscript 命令行而不是文件中定义。使用 endpage.ps 和 DrawingSheet.ps 文件作为参数运行 ghostscript。需要做更多的工作才能将其调整为 DrawingSheet.pdf,除非这是可能的。
在更改最终页码后看看这是否有效。在执行 showpage 之前,table.ps 应该放在原始最后一页的顶部。
%!
/finalpage 9 def
<<
/EndPage {
2 ne {
1 add finalpage eq {(found last page\n)print (Table.ps)run} if
currentpagedevice /PageCount get ==
true
} if
}
>> setpagedevice
编辑:Postscript 语言参考手册 3 第 176 页说:
PostScript 解释器维护一个隐含的当前页面,该页面累积绘制操作员所做的标记。当程序开始时,当前页面完全空白。当每个绘制操作符执行时,它会在当前页面上放置标记。每个新标记都完全掩盖了它可能覆盖的任何标记。这种方法被称为绘画模型:无论标记有什么颜色——白色、黑色、灰色或彩色——它都被放置在当前页面上,就好像它是用不透明的油漆涂抹的一样。页面完全合成后,调用 showpage 运算符会在输出媒体上呈现累积的标记,然后再次将页面清除为白色。
,经过多次尝试和错误,当然还有来自诸如@beginner6789 和@luserdroog 之类的 SO 用户的建议/评论(感谢他们两人),我终于得到了适合我的案例的东西。我将总结我的实验和发现以造福他人。
在本次讨论中,假设您想将来自 Overlay.*
(.ps 或 .pdf)的页面叠加在来自 Base.*
(.ps 或 .pdf)的特定页面之上。似乎没有一种解决方案适合所有场景。这取决于:
- 如果您有
Overlay.ps
或Overlay.pdf
。虽然转换它们很容易。 - 如果您有
Base.ps
或Base.pdf
。虽然转换它们很容易。 - 如果
Overlay.ps
或Base.ps
是从相应的 pdf 文件自动生成的,或者它们是手写的。我发现与自动生成的 PostScript 文件相比,手写的 PostScript 文件更加清晰、精确和优化。 - 逻辑变得更加复杂,这取决于您希望将叠加文件的哪一页/几页叠加在 Base 文件的哪一页/几页之上。您可能需要做一些额外的工作来识别这些页面。
以下是我尝试过的 3 种解决方案。总结一下:解决方案 3 对我有用,如相应结果表的最后一行所述。
解决方案 1:
创建以下 Merge.ps
并通过您的 GhostScript 运行它以生成 PDF 输出:
1 dict begin
/showpage {} def
(Base.ps) run % or Base.pdf
(Overlay.ps) run % or Overlay.pdf
end
showpage
结果:
基础文件 | 叠加文件 | 结果/注释 |
---|---|---|
Base.pdf | Overlay.ps(手写) | 覆盖文件附加在基本文件的末尾 |
Base.pdf | Overlay.ps(从 PDF 转换而来) | 覆盖文件附加在基本文件的末尾 |
Base.pdf | 叠加.pdf | 覆盖文件并在基本文件的末尾附加一个空白页 |
Base.ps(从 PDF 转换而来) | Overlay.ps(手写) | 单页PDF,基本文件和覆盖文件的所有页面相互叠加 |
Base.ps(从 PDF 转换而来) | Overlay.ps(从 PDF 转换而来) | 单页 PDF,仅包含来自 Overlay 文件的页面 |
Base.ps(从 PDF 转换而来) | 叠加.pdf | 与 Overlay 文件相同,末尾附加空白页 |
如果 Base 文件是多页文件,这似乎不是一个合适的选项。
解决方案 2:
创建以下 Merge.ps
并通过您的 GhostScript 和 Base 文件运行它以生成 PDF 输出:
<<
/EndPage
{
2 eq
{
pop false
}
{
1 dict begin
/showpage {} def
(Overlay.ps) run % or Overlay.pdf
end
pop true
} ifelse
} bind
>> setpagedevice
如果您只想在基本文件的某些页面上叠加,则需要额外的逻辑。
结果:
基础文件 | 叠加文件 | 结果/注释 |
---|---|---|
Base.pdf | Overlay.ps(手写) | 覆盖文件叠加在基础文件的每一页之上 |
Base.pdf | Overlay.ps(从 PDF 转换而来) | Base 文件中的每个页面都替换为 Overlay 文件中的页面 |
Base.pdf | 叠加.pdf | 堆栈溢出后 GhostScript 崩溃(无双关语) |
Base.ps(从 PDF 转换而来) | Overlay.ps(手写) | 覆盖文件叠加在基础文件的每一页之上 |
Base.ps(从 PDF 转换而来) | Overlay.ps(从 PDF 转换而来) | Base 文件中的每个页面都被 Overlay 文件中的页面替换 |
Base.ps(从 PDF 转换而来) | 叠加.pdf | GhostScript 崩溃 |
解决方案 3:
编辑从 Base.pdf 转换而来的 Base.ps 文件。找到与您要叠加的页面对应的条目%%EndPageSetup
,并在其后插入以下代码。通过您的 GhostScript 运行它以生成 PDF 输出。在下面的示例中,我正在为第三页编辑它:
% BUNCH OF CODE NOT SHOWN HERE %
%%Page: 3 3
%%PageBoundingBox: 0 0 792 612
%%BeginPageSetup
8 0 obj
<</Type/Page/MediaBox [0 0 792 612]
/Parent 3 0 R
/Resources<</ProcSet[/PDF]
>>
/Contents 9 0 R
/CropBox
[0 0 792.0 612.0]
>>
endobj
%%EndPageSetup
1 dict begin % <== My Edits
/showpage {} def % <== My Edits
(Overlay.ps) run % <== My Edits
% [1 0 0 -1 0 612] concat % <== My Edits. See Notes below.
end % <== My Edits
9 0 obj
% BUNCH OF CODE NOT SHOWN HERE %
结果:
基础文件 | 叠加文件 | 结果/注释 |
---|---|---|
Base.ps(从 PDF 转换和编辑) | Overlay.ps(手写) | Overlay 页面叠加在 Base 文件的第三页之上 |
Base.ps(从 PDF 转换和编辑) | Overlay.ps(从 PDF 转换而来) | 覆盖页面叠加在Base文件的第三页之上,但是base文件的第三页显示为原始第三页的X轴镜像 |
Base.ps(从 PDF 转换和编辑) | 叠加.pdf | Base 文件的四页输出,其中 Overlay 页作为第三页插入。 |
Base.ps(从 PDF 转换并编辑) | Overlay.ps(从 PDF 转换而来,上面的代码没有注释转换矩阵连接) | Overlay 页面按照我的需要叠加在 Base 文件的第三页之上。这个场景适合我 |
就我而言:
- 我无法控制 Base.pdf 文件的生成方式,但我可以使用 GhostScript 将其转换为 Base.ps。
- 我可以部分控制 Overlay 文件的生成。我有 XML 数据,我使用 XSLFO 将其转换为表格格式,然后使用 Apache FOP 将其转换为 PDF 和 PostScript 文件。
- 我真的没有选择手动编写 Base.ps 或 Overlay.ps。
考虑到所有这些试验和错误的结果,此时 Solution-3(在运行命令后连接转换矩阵,结果表的最后一行)对我有用。我不是特别喜欢这个选项,因为它涉及编辑自动生成的 PostScript 文件。
注意:对于所有我看到来自基本文件的页面被覆盖页面替换的情况,我认为来自基本文件的原始页面打印在输出页面大小之外,因此它被剪裁并且不显示并显示为被替换。也许对转换矩阵的正确操作可以解决这些情况。我还没有尝试过这种情况,但不知道如何验证。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。