裁剪标记未在重影脚本中设置在正确位置

Posted

技术标签:

【中文标题】裁剪标记未在重影脚本中设置在正确位置【英文标题】:Crop marker not set in proper position in ghost script 【发布时间】:2020-05-13 13:17:40 【问题描述】:

我尝试在 pdf 文件中添加裁剪标记。但裁剪标记未设置在右侧或右侧角落的顶部。我尝试通过 postscript 获取页面大小并设置标记,但我的 postscript 获取新的页面宽度和高度并设置标记但标记位置不正确。 我的幽灵命令是:- gswin64c.exe -o E:\output.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 test.ps -f E:\comic.pdf

inout 或输出文件链接 Input PDF Output PDF

我的裁剪标记后记是

    <<
/BeginPage 
    /count exch def % of previous showpage calls for this device
 bind
/EndPage 

    /pagewidth  currentpagedevice /PageSize get 0 get def
    /pageheight currentpagedevice /PageSize get 1 get def
    /y pageheight 9 sub def
    /x pagewidth 9 sub def

    newpath
    -1 -1 moveto
    0 9 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke


    newpath
    x -1 moveto
    0 9 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    1 setlinewidth
    grestore
    stroke


    newpath
    x y moveto
    0 10 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke

    newpath
    -1 y moveto
    0 10 rlineto
    10 0 rlineto
    0 -10 rlineto
    -10 0 rlineto
    closepath
    gsave
    grestore
    1 setlinewidth
    stroke


    % return (output=) true only for showpage.
    code 0 eq

>> setpagedevice

【问题讨论】:

您有什么要求?有很多pdf文件可以转换吗?初始大小是否总是相同的 496x756?最终尺寸是否始终为 396x612?您的命令行始终将解释器设置为创建 396x612 输出,因此不关心输入大小,因此忽略信息。这些示例在将原始页面实际调整为新的 PageSize 之前将裁剪标记放在页面上,这显然必须在 EndPage 完成之后。我发现一个两步蒸馏过程首先放置裁剪标记,然后调整页面大小。这对您的目的有用吗? 【参考方案1】:

理想情况下,当您运行 BeginPage 或 EndPage 过程时,您不应简单地在当前字典中创建新的键/值对。原因是在执行这些字典时,您不能确切地依赖哪个字典恰好位于字典堆栈的顶部,并且可能会有所不同。

这可能导致您希望出现的键未定义,并且可能(可能)导致您覆盖字典中已有的键/值对。

事实上,在 PostScript 中,通常认为更好的做法是根本不在字典中定义瞬态变量,而只是将它们存储在堆栈中并从那里访问它们。这消除了覆盖值的可能性,并且堆栈操作通常比字典操作更快,因此也有(轻微的)性能优势。

您的 EndPage 程序会执行所有计算并执行笔划,即使它不会将页面传输到设备,这显然是浪费,您应该使用 if 代替。您将 gsave 和 grestore 作为一对一起使用,这在性能方面毫无意义且非常昂贵。这是图形状态的保存和恢复,如果你在这之间不做任何事情,它就没有效果。

最后,您的 BeginPage 过程定义了 /count,但您似乎并没有真正用它做任何事情!

如果我是你,我会将这些重写为:

/BeginPage 
    userdict /MyDict known    %% is MyDict alreadly present in userdict ?
    
        userdict /MyDict get  %% If it is, then get it
    
    
        userdict begin        %% start userdict (makes it top element on dict stack)
        /MyDict               %% Put key /MyDict on stack
                              %%   stack - /MyDict
        5 dict                %% make a 5 element dictionary
                              %%   stack - /MyDict -dict-
        dup                   %% make a copy (duiplicates a pointer)
                              %%   stack - /MyDict -dict -dict-
        3 1 roll              %% rotate the stack
                              %%   stack -dict /MyDict -dict
        put                   %% Put the top element on the stack in the current
                              %% dictionary, using the key second top on the stack
                              %%    stack -dict-
        end                   %% close userdict
     ifelse
    begin                     %% make the top element on the stack the current
                              %% dictionary.
    /count exch def           %% store the count ot pages in the currnt dictionary
                              %% using the key /count.
    end                       %% close the current dictionary

显然,您可以删除所有 cmets,它们纯粹是解释性的。从此时起,您可以通过执行以下操作找到与 count 关联的值:

userdict /MyDict get /count get

然后:

/EndPage 
                                 %% We enter with the reason code on the stack
    0 eq                        %% We only want to take action for 0 (showpage)
      gsave
      currentpagedevice          %% Get the current page device dictionary
                                 %%    stack -dict-
      /PageSize get              %% get the value associated with the key /PageSize
                                 %% from that dictionary.
                                 %%    stack -array-
      dup dup                    %% make some copies of the array
                                 %%     stack -array- -array- -array-
      0 get                      %% get element 0 from the array
                                 %%     stack -array- -array- 'x'
      9 sub                      %% subtract 9 from the value
      0 put                      %% put that into array element 0
                                 %%      stack -array-
      dup dup 1 get              %% repaeat for element 1
      9 sub 1 put

      newpath
      -1 -1 moveto
      0 9 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      dup 0 get                  %% duplicate the array, get the 0th element
      -1 moveto                  
      0 9 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath
      
      dup 0 get                  %% duplicate the array, get the 0th element
                                 %% stack -array- 'x'
      1 index                    %% copy the element one down the stack to the top
                                 %% stack -array- 'x' -array-
      1 get                      %% get element 1 of the array
                                 %% stack -array- 'x' 'y'
      moveto
      0 10 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      1 get                      %% get element 1 from the array
      -1 exch moveto
      0 10 rlineto
      10 0 rlineto
      0 -10 rlineto
      -10 0 rlineto
      closepath

      1 setlinewdith
      stroke

      grestore
      true
    
    
      false
    ifelse

请注意,我没有测试代码,它只是为了说明。

现在真正的重点是,你的笔画错位的原因是因为你已经缩放了页面。

-dFitPage 通过调整当前转换矩阵来缩放页面内容以适应新的页面尺寸。在该点之后的所有内容都将被缩放,这包括 EndPage 过程中的路径构造。

演示;尝试在没有-dFIXEDMEDIA 等的情况下执行命令行,您应该会看到页面显示为原始大小并且笔划在正确的位置。

为了正确放置笔划,您需要知道应用了哪个比例因子,并将坐标值乘以该数量的倒数。也就是说,如果比例因子为 0.5(即一半大小),则您需要将位置乘以 2。

【讨论】:

代码在 Error: /typecheck in /--.endpage-- 或 /--beginpage 中抛出错误。你能解释一下吗 如果我删除 -dFIXEDMEDIA 则对输出 pdf 没有任何影响,但如果我删除 -dPDFFitPage 则输出 pdf 大小不会改变 如果你得到一个错误'tyepecheck',那么这意味着程序使用了一个操作符,期望一个特定类型的数据(例如一个整数)并且提供了一个不同类型的数据。显然程序中有一个错误,我确实说过它未经测试。是的,显然如果您删除 -dPDFFitPage 大小不会改变,那就是重点。如果你这样做,你会看到你的 copr 标记在正确的位置。您的问题是 CTM 已缩放,您需要对坐标应用反向缩放,或使用适用于原始页面的坐标。 我尝试解决 /typecheck 错误,但我无法..你能检查一下吗。这对我来说很紧急。如果您有任何其他示例可以使用 ghost 命令行添加裁剪标记 就用你现有的代码吧,这可能是最简单的。【参考方案2】:

这很有趣。经过测试,仅放置裁剪标记且没有错误,但仍然没有反向缩放,因此不适用于即时调整大小。转向两步再蒸馏的决定将取决于要求,因为两步方法现在有效,而进一步的开发可以在未来实现多合一的结果。

<<  /EndPage  exch pop   % page number unneeded

0 eq  pop       % ifelse

gsave

currentpagedevice /PageSize get
dup 0 get 9 sub exch 1 get 9 sub

2 array astore       % put in new array

newpath
-1 -1 moveto
0 9 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
%    x
dup 0 get
-1 moveto
0 9 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
%    x y 
dup aload pop
moveto
0 10 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

newpath
1 get
%    -1 
%    y
-1 exch
moveto
0 10 rlineto
10 0 rlineto
0 -10 rlineto
-10 0 rlineto
closepath
1 setlinewidth
stroke

grestore

% return (output=) true only for showpage.
truepop falseifelse


 >> setpagedevice

%showpage   % shortcut for testing

编辑:这是两个步骤:

gs -o comic11-cropmarks.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite cropmarks1.ps -f comic11.pdf
gs -o comic11-resized.pdf -dBATCH -dNOPAUSE -dDOPDFMARKS -sDEVICE=pdfwrite -dFIXEDMEDIA -dPDFFitPage -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 -f comic11-cropmarks.pdf

EDIT2:这些重新蒸馏会导致 dpi 发生变化,因此如果需要 300dpi 分辨率,那么也可以使用 ghostscript 进行更改。以下是有关两步过程结果的一些信息:

$ pdfimages -list comic11.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceGray bpc=8

$ pdfimages -list comic11-cropmarks.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=300.00 vdpi=300.00 colorspace=DeviceGray bpc=8

$ pdfimages -list comic11-resized.pdf tmp/
tmp/-0000.ppm: page=1 width=2063 height=3150 hdpi=375.09 vdpi=375.09 colorspace=DeviceRGB bpc=8
tmp/-0001.pgm: page=1 width=2063 height=3150 hdpi=375.09 vdpi=375.09 colorspace=DeviceGray bpc=8

【讨论】:

【参考方案3】:

这是一个多合一的解决方案。我不得不更改 ghostscript 命令行。

编辑:这是一个 postscript all-in-one comic.ps,因为你说页面大小不适用于我之前的尝试:

%!
true setstrokeadjust
0.5 setlinewidth 1.0 0.9 0.9 setrgbcolor
[ 7.7 10 381 591 ] dup rectfill
1 0 0 setrgbcolor rectstroke 0.9 0.9 1.0 setrgbcolor
[ 15 18 366.5 575.5 ] dup rectfill
0.3 setlinewidth 0 0 1 setrgbcolor rectstroke
0 0 0 setrgbcolor
[ 7.7 10 -10 -10 ] rectstroke
[ 7.7 601 -10 10 ] rectstroke
[ 388.5 601 10 10 ] rectstroke
[ 388.5 10 10 -10 ] rectstroke

/centre  dup stringwidth pop 2 div 396 2 div exch sub  def
/Helvetica-BoldOblique 10 selectfont

(ARTWORK MUST EXTEND PAST RED LINES ON ALL PAGES.) centre 500 moveto show
(THIS IS THE TRIM LINE.) centre 478 moveto show
(ARTWORK BEYOND THE TRIM LINE WILL FALL INTO SPINE) centre 456 moveto show
(OR BE CUT OFF. THE ACTUAL CUT MAY VARY UP TO 1/8" FROM) centre 434 moveto show
(THIS LINE TO EITHER SIDE DURING PRODUCTION.) centre 412 moveto show
(BLUE AREA IS THE "SAFE" ZONE.) centre 390 moveto show
(BE SURE ALL TEXT AND IMPORTANT IMAGES ARE) centre 368 moveto show
(KEPT WITHIN THE BLUE AREAS.) centre 346 moveto show
(ALL NON-WHITE BORDERS AND FILLS) centre 324 moveto show
(SHOULD EXTEND TO EDGE OF PAGE. \(WHITE AREA\)) centre 302 moveto show
(TEMPLATE RESOLUTION IS SET TO 300 DPI.) centre 280 moveto show
(THIS IS PRINT-READY AND SHOULD NOT BE CHANGED.) centre 258 moveto show
1 0 0 setrgbcolor
(THESE NOTES ARE ON THE "TEMPLATE" LAYER) centre 136 moveto show
(AND SHOULD BE DELETED BEFORE EXPORTING) centre 114 moveto show
(FINAL FILES FOR PRINT.) centre 92 moveto show
showpage

这只是一个例子。可以编辑后记以解决任何其他问题。这是我的 ghostscript 命令行:

gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -r300 -dPDFFitPage -dFIXEDMEDIA -dDEVICEWIDTHPOINTS=396 -dDEVICEHEIGHTPOINTS=612 -sOutputFile=comic.pdf -f comic.ps

EDIT3:修复了通过将上述后记矩形覆盖到调整大小的comic11.pdf上直到它们匹配的数字。

EDIT4:将“> setpagedevice”添加到上述后记的开头允许使用 ps2pdf 创建具有正确页面大小的 pdf。

【讨论】:

在正确位置裁剪标记,但最终 PDF 大小不符合 396x612。所以这是不对的 尝试我之前帖子中的两步转换,而不是一体式转换。我可以想到很多方法来做到这一点,只是不知道真正需要什么。我会从头开始,在后记中做所有事情,然后可以精确地指定尺寸并创建一个好的 pdf。如果需要,comic11.pdf 中有两个图像可以提取和调整大小(pnm 和 pgm)。如果没有,那么后记将非常容易。如果您只需要一份有效的 pdf,请尝试我的两步答案。

以上是关于裁剪标记未在重影脚本中设置在正确位置的主要内容,如果未能解决你的问题,请参考以下文章

sqlplus中设置在屏幕中上不打印出输出

Barrier 未在约束布局中设置为 referenceIds?

新标记已更新其位置,但旧标记未在离子原生谷歌地图中删除

未在聚合物上显示位置(使用 Google 地图)

Eclipse中设置在创建新类时自动生成注释

JAVA_HOME 变量未在 Windows 中设置 [重复]