微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 PDF 文件上叠加一个 PS 文件

如何解决在 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.pdfTable.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 - 附加说明:如果我从上面的代码中注释掉 gsavegrestore,那么我不会得到空白页,而是现在每一页都是用 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 轴的中心上翻转。页面截图为:

enter image description here

你能读到的文字来自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.psOverlay.pdf。虽然转换它们很容易。
  • 如果您有 Base.psBase.pdf。虽然转换它们很容易。
  • 如果 Overlay.psBase.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 举报,一经查实,本站将立刻删除。