确定Postscript中的页面方向

祖瑟

我需要使用Ghostscript在PDF文档的每一页的左下角添加一个白色矩形和一些文本。为此,我创建了以下Postscript脚本:

<<
   /EndPage
   {
     2 eq { pop false }
     {
        newpath
        0 0 moveto
        0 20 lineto
        200 20 lineto
        200 0 lineto
        closepath
        %%gsave
        1 setgray
        fill
        %%grestore
        1 setlinewidth
        0 setgray
        stroke

        gsave
        /Times-Roman 9 selectfont              
        30 5 moveto                            
        (My text) show

        grestore
        true
     } ifelse
   } bind
>> setpagedevice

与Ghostscript命令结合使用时,效果很好:

gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=output.pdf my_script.ps input.pdf

但是,如果input.pdf处于横向模式,则白框和文本打印在左上角而不是左下角。我可以通过添加以下内容使其起作用:

90 rotate 0 -595 translate

但是我无法确定页面何时处于横向模式还是纵向模式。我可以获得页面的宽度和高度,但是即使对于横向模式页面,其宽度也小于高度。我尝试了以下操作,但失败了:

/orient currentpagedevice /Orientation get def

我已经坚持了一段时间。任何帮助是极大的赞赏!

(Ghostscript版本为9.25)

[更新]

为了说明如何宽度大于高度,在横向模式下一个页面时,这里是我使用的script.ps:https://gist.github.com/irinkaa/9faadf30b3a5a381a0b621d72b712020

这是input.pdfoutput.pdf如您所见,它612.0 - 792.0被打印在输出文件中,显示宽度(612)<高度(792)。

当我在输出文件上重新运行相同的命令时,它会打印相同的宽度和高度值,但随后将该框正确放置在左下角。

当我在脚本中添加以下内容时:

/orient currentpagedevice /Orientation get def

我收到一条错误消息,提示未设置方向(如果我理解正确的话):

Error: /undefined in --get--
Operand stack:
   orient   --dict:212/312(ro)(L)--   Orientation
Execution stack:
   %interp_exit   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--   --nostringval--   --nostringval--   false   1   %stopped_push   1999   1   3   %oparray_pop   1998   1   3   %oparray_pop   1982   1   3   %oparray_pop   1868   1   3   %oparray_pop   --nostringval--   %errorexec_pop   .runexec2   --nostringval--   --nostringval--   --nostringval--   2   %stopped_push   --nostringval--
Dictionary stack:
   --dict:977/1684(ro)(G)--   --dict:0/20(G)--   --dict:80/200(L)--
Current allocation mode is local
Current file position is 151
GPL Ghostscript 9.25: Unrecoverable error, exit code 1
肯斯

首先,您应该升级您的Ghostscript版本。9.25很旧,并且具有安全漏洞。

其次,您需要查看页面设备字典中的/ Orientation/ PageSize条目。不仅如此,您还应该使用PageSize来确定用于“调整”的翻译。除非您处于固定的工作流程中(如果您正在接收混合的方向文件,这似乎不太可能),那么您不应假定介质为A4。

Ghostscript PDF解释器查看PDF文件每一页上的MediaBox,并重置页面设备字典中的/ PageSize以匹配该页面的MediaBox。如果PDF页面具有/ Rotate条目,则它将(IIRC)永不设置/ Orientation,然后将其应用于MediaBox和页面的内容。

因此,您实际上只需要查看所请求媒体的宽度和高度,这是由页面设备字典中的/ PageSize数组给出的。

现在这么说...

您说“即使对于横向模式页面,宽度也小于高度”。这对我来说似乎不太可能,但是在没有示例的情况下很难说出来。这也使任何人都很难提供任何建议。

我建议您将示例上传到某个地方,然后在此处发布URL,以便我们查看文件。

哦,我真的建议您不要将输出文件发送到stdout。这可能对您来说很方便,但是pdfwrite设备已经具有某些功能,如果您这样做就根本无法使用(它们要求输出文件可搜索),并且将来可能还会有更多情况。

[编辑]

您的问题是执行顺序。script.ps中的程序在解释PDF文件之前运行,然后解释PDF文件。

当您的程序正在做的所有事情都是在页面设备字典中设置EndPage过程时,这是没有问题的,对页面设备字典的更改是保守的,除非特别是过度改写,否则它们会累积。

因此,在解释PDF文件的过程中页面设备字典发生更改这一事实无关紧要(除非以某种方式更改了EndPage过程)。

但是在程序运行时,页面设备字典/ PageSize键具有关联的值,该值是一个包含默认媒体大小的数组(因为尚未发生任何更改)。在解释PDF文件之前,不会更改PageSize条目。这意味着无论您的PDF文件使用哪种尺寸的介质,您的程序都将始终返回默认的介质尺寸。

您需要在执行EndPage过程时知道实际的PageSize。因此,您需要在EndPage过程中研究当前的PageSize。

就像是:

<<
   /EndPage
   {
     2 eq { pop false }
     {
       % Get the current page device dictionary and extract the PageSize
       currentpagedevice /PageSize get

       % Load the values from the array onto the stack
       % and discard the array copy returned by the aload operator
       aload pop

       % If width < height (or equal, square page)
       le {
         % Handle a portrait page
       } {
         % Handle a landscape page
       } ifelse
    }ifelse
  } bind
>> setpagedevice

请注意,这避免了创建字典条目来保存页面的宽度和高度。这样做有几个原因;

首先,每个页面的宽度和高度都可以不同(尤其是在PDF文件中)。

其次,您不(在程序中)创建自己的字典来存储这些键/值对,这意味着您正在使用当时处于活动状态的任何字典。尽管这是您当前所接受的方式,但是由于userdict将在程序开始时处于活动状态,因此您无法知道调用EndPage时哪个词典位于词典堆栈的顶部。因此,仅将值戳入碰巧是最重要的字典中是不安全的,您可能最终会覆盖具有相同名称的键,这将导致不可预知的副作用。同样地(按照下面的方向),如果当前字典中不包含这些键,则将得到未定义的错误。因此,您现在正通过运气摆脱困境。

第三,在PostScript中通常认为更好的做法是使用堆栈进行临时存储,而不是在字典中创建键/值对。

由于后两个原因,我强烈建议您不要stringholder在程序开始时在字典堆栈顶部的任何字典中创建一个称为(如您的程序当前那样)的键,并假设它在EndPage过程,您应该改为使用10 string简单地创建一个临时字符串

例如:

/Times-Roman 9 selectfont              
30 5 moveto                            
pagewidth
stringHolder cvs
show

会成为:

/Times-Roman 9 selectfont              
30 5 moveto                            
currentpagedevice /PageSize get 0 get
256 string cvs
show

10位数字可能有点小,任何人都应该足够256位,并且字符串将被垃圾回收,因此这不像您正在泄漏内存或其他任何东西。

关于方向;是的,您是正确的,正如我最初所说的,PDF解释器未在页面设备字典中设置“方向”。如果您尝试get从不包含该键的字典中键入一个键,则会收到未定义的错误。如果不确定字典中是否存在键,则应首先使用known运算符对其进行检查

[编辑2]

如以下注释中所述...可以通过使用transform运算符和单位矢量来测试CTM的方向如果由此产生的两个坐标中的一个或两个transform均为负,则CTM中涉及旋转,并且通过检查每个坐标的符号,我们可以确定旋转最终位于哪个象限。

对于PDF中的/ Rotate标志而言,这已足够,因为只能以90度为增量进行指定。这是一个确定旋转的示例函数,以及一个简单的PostScript行使它:

%!PS

/R {
1 1 transform

0 ge {
  0 ge {
    (no rotation\n) print
  } {
    (90 degree ccw rotation\n) print
  } ifelse
} {
  0 ge {
    (270 ccw rotation\n) print
  } {
    (180 ccw rotation\n) print
  } ifelse
} ifelse
} bind def

R
gsave
90 rotate R
grestore
gsave
180 rotate R
grestore
gsave
270 rotate R
grestore
gsave
360 rotate R
grestore

可以使用此技术来确定原始文件是否已旋转,然后选择使EndPage过程具有不同的行为。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Aspose中的页面方向

来自分类Dev

如何确定图像中的物体方向?

来自分类Dev

在Android中更改特定页面的方向

来自分类Dev

在Android中更改特定页面的方向

来自分类Dev

处理 Xamarin 中的页面方向更改

来自分类Dev

页面在laravel中未正确定向

来自分类Dev

多页方向-Adobe Postscript的工具

来自分类Dev

如何确定 scilab 3dplot 中顶点的方向?

来自分类Dev

使用ghostscript为Postscript文件中的某些页面添加Duplex选项

来自分类Dev

如何确定NSLayoutConstraint方向?

来自分类Dev

在“显示页面”之前注入PostScript代码

来自分类Dev

CodeIgniter页面方向中的mPDF不会横向显示

来自分类Dev

ASP.NET中的页面/控件事件冒泡方向

来自分类Dev

如何在多页 NSPrintOperation 中更改页面方向?

来自分类Dev

确定Magento中CMS页面的所有商店?

来自分类Dev

确定Wordpress中类别页面模板的类别标识符

来自分类Dev

在Java中使用Selenium来确定页面中iframe的数量?

来自分类Dev

Postscript中的LOCAL做什么?

来自分类Dev

最后更改页面方向

来自分类Dev

最后更改页面方向

来自分类Dev

JODConverter页面方向

来自分类Dev

确定指南针方向

来自分类Dev

您如何确定谓词“方向”?

来自分类Dev

确定谷歌地图的拖动方向

来自分类Dev

方向确定算法混合左右

来自分类Dev

如何确定主屏幕的方向

来自分类Dev

是否可以在本地Windows 8.1桌面应用程序中确定屏幕方向?

来自分类Dev

在AngularJs中,如何确定在页面中多次使用的控制器中的特定作用域?

来自分类Dev

使用Ghostscript(PostScript)计算来自stdin的PDF页面