仅在相当锁定的裸机Linux机器上使用Ghostscript,我需要将三个现有的PDF合并为一个新PDF,在新PDF的每一页上放置一个静态标头,在新PDF的每一页上放置一个静态页脚PDF,并为每个页面编号(例如“ Page 1257”)。
我对前三个问题有解决方案。开箱即用的Ghostscript可以轻松地将多个PDF合并为一个新PDF。通过在-c命令行选项中修改PostScript,我可以将静态页眉和页脚添加到新的PDF中。我还不能做的就是将页码放在新的PDF中。
这是我现在拥有的复杂命令行:
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=final.pdf -c "<</EndPage {2 ne {200 0 0 setrgbcolor /NimbusSans-Bold 24 selectfont 240 2 moveto (Static Footer) show 240 773 moveto (Static Header) show 0 0 0 setrgbcolor /NimbusSans-Regular 12 selectfont 2 24 moveto (Page ) show true}{pop false} ifelse} >> setpagedevice" -f title.pdf parta.pdf partb.pdf
删除静态的页眉和页脚片段会变得更简单一些:
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=final.pdf -c "<</EndPage {2 ne {0 0 0 setrgbcolor /NimbusSans-Regular 12 selectfont 2 24 moveto (Page ) show true}{pop false} ifelse} >> setpagedevice" -f title.pdf parta.pdf partb.pdf
我已经尝试了很多方法来显示页码,但是它们要么使Ghostscript崩溃,要么仅在每页上显示相同的页码。唯一的其他麻烦是新的PDF将在1,000至2,000页之间。
我需要一个很好的代码示例,说明如何使PostScript在PDF的每一页上显示递增的页码。
答案 0 :(得分:0)
在PostScript中计数页面并不难。我希望您已经了解以下大多数内容,但是我将采取一些小步骤,以使以后遇到此问题的其他人受益。
我们首先创建一个我们自己的字典来存储内容。我们确保在'userdict'中定义了它,以便我们始终可以找到它(userdict和systemdict一样总是可用的)。选择的名称应该唯一,以防止其他PostScript或PDF文件覆盖它!
userdict begin %% Make userdict the current dictionary
/My_working_Dict %% Create a name for our dict (choose something unique)
10 dict %% create a 10-element dictionary
def %% def takes a key and value and puts them in the current dictionary
My_working_Dict begin %% make our working dictionary the current one
/PageCount %% Make a name for our counter
0 %% 0, this will be the initial value
def %% define PageCount as 0 in the current dictionary
end %% close the current dictionary (My_working_Dict)
end %% close the current dictionary (userdict)
有更有效的方法来执行此操作,但这是一种易于描述和遵循的方法。从这一点开始,直到我们关闭PostScript解释器(或将其还原回以前的状态),userdict将包含一个名为My_working_Dict的字典,该字典将具有一个称为PageCount的键。与PageCount关联的值最初将为0,但是我们可以更改它。
您已经定义了这样的EndPage过程:
<<
/EndPage {
2 ne {
200 0 0 setrgbcolor
/NimbusSans-Bold 24 selectfont
240 2 moveto
(Static Footer) show
240 773 moveto
(Static Header) show
0 0 0 setrgbcolor
/NimbusSans-Regular 12 selectfont
2 24 moveto
(Page ) show
true
}
{
pop
false
} ifelse
}
>> setpagedevice
现在,当调用EndPage过程时,堆栈上有两个数字,最上面的数字是“原因码”,下一个数字是先前显示页面执行的次数。现在您会认为(合理地)可以使用该计数作为页数,但是不幸的是,每次调用“ setpagedevice”时,它都会重置为0,并且PDF解释程序会在每个页面上调用setpagedevice,因为它可能对PDF中的每个页面都有效文件大小不同,而setpagedevice是我们更改页面大小的方式。
当我们从EndPage过程返回时,必须在堆栈上压入一个布尔值,即“ true”(将页面发送到输出)或“ false”(将其丢弃并且不执行任何操作)。
因此,您的过程将测试原因代码以查看为何调用了EndPage。如果其不是“ 2”(设备被停用),则为复制页面或显示页面,因此您可以在页面上绘制所需的添加内容。如果它是2,那么我们只是弹出页面数并返回'false',这样我们就不会尝试发出多余的页面。
如果为2,则将颜色设置为RGB黑色(可以改为0 setgray
)找到字体NimbusSans-Bold,将其缩放为24点并将其设置为当前字体。然后,移至位置x = 240,y = 2(0,0位于左下角,单位是点,1/72英寸)并绘制文本“ Static Footer”(NB括号是PostScript中的字符串定界符)< / p>
然后您将移动到x = 240,y = 773并绘制文本“静态标题”。
然后您再次冗余地设置颜色,不需要这样做,直到您对其进行更改之前,它保持不变,然后再次找到字体NimbusSans-Bold,这次将其缩放为12点并将其选择为当前字体。最后,您移动到x = 2,y = 24的位置并绘制了文本'Page'。
因此,您所需要做的就是扩展EndPage过程,以便它从我们的词典中提取页面数,将其转换为字符串,然后绘制结果字符串。
类似的东西:
userdict begin %% Make userdict the current dictionary
/My_working_Dict %% Create a name for our dict (choose something unique)
10 dict %% create a 10-element dictionary
def %% def takes a key and value and puts them in the current dictionary
My_working_Dict begin %% make our working dictionary the current one
/PageCount %% Make a name for our counter
0 %% 0, this will be the initial value
def %% define PageCount as 0 in the current dictionary
end %% close the current dictionary (My_working_Dict)
end %% close the current dictionary (userdict)
<<
/EndPage {
2 ne {
0 0 0 setrgbcolor
/NimbusSans-Bold 24 selectfont
240 2 moveto
(Static Footer) show
240 773 moveto
(Static Header) show
0 0 0 setrgbcolor
/NimbusSans-Regular 12 selectfont
2 24 moveto
(Page ) show
userdict /My_working_Dict get %% get My_working_dict from userdict (leaves My_working_dict on the operand stack
dup %% duplicate the dictionary reference
/PageCount get %% get PageCount from the dictionary on the stack
1 add %% add one to the count
/PageCount %% put the key on the stack
%% stack now holds << >> int /PageCount
%% where << >> is a reference to My_working_Dict, int is our new value for PageCount, and /PageCount is the key name we are using
exch %% swap the topmost two stack items
%% stack is now << >> /PageCount int
put %% puts the top two items on the stack into the dictionary which is third on the stack.
256 string %% Temporary string to hold the count
userdict /My_working_Dict get %% get My_working_dict from userdict (leaves My_working_dict on the operand stack
/PageCount get %% get PageCount from the dictionary on the stack
exch
cvs %% Convert the top object on the stack into a string, storing the result in the second object down, whic must be a string
show %% draw the string on the page using the current colour and font.
true
}
{
pop
false
} ifelse
}
>> setpagedevice
然后您将使用以下命令执行Ghostscript:
gs -dNOPAUSE -dBATCH -sDEVICE = pdfwrite -sOutputFile = final.pdf ModifyPDF.ps title.pdf parta.pdf partb.pdf
现在我实际上还没有尝试过此代码,因此完全有可能出现错误。
[更新2]
该程序基本相同,但是将变量存储在全局VM中的一本字典中,并存储在globaldict中,以免保存/恢复。
globaldict begin %% Make globaldict the current dictionary
currentglobal true setglobal %% We need to make the VM allocation mode for the dictionary global
/My_working_Dict %% Create a name for our dict (choose something unique)
10 dict %% create a 10-element dictionary
def %% def takes a key and value and puts them in the current dictionary
setglobal %% put the VM allocation mode back
globaldict /My_working_Dict %% Get the dictionary from globaldict
get begin %% make our working dictionary the current one
/PageCount %% Make a name for our counter
0 %% 0, this will be the initial value
def %% define PageCount as 0 in the current dictionary
end %% close the current dictionary (My_working_Dict)
end %% close the current dictionary (globaldict)
<<
/EndPage {
2 ne {
0 0 0 setrgbcolor
/NimbusSans-Bold 24 selectfont
240 2 moveto
(Static Footer) show
240 773 moveto
(Static Header) show
0 0 0 setrgbcolor
/NimbusSans-Regular 12 selectfont
2 24 moveto
(Page ) show
globaldict /My_working_Dict get %% get My_working_dict from globaldict (leaves My_working_dict on the operand stack
dup %% duplicate the dictionary reference
/PageCount get %% get PageCount from the dictionary on the stack
1 add %% add one to the count
/PageCount %% put the key on the stack
%% stack now holds << >> int /PageCount
%% where << >> is a reference to My_working_Dict, int is our new value for PageCount, and /PageCount is the key name we are using
exch %% swap the topmost two stack items
%% stack is now << >> /PageCount int
put %% puts the top two items on the stack into the dictionary which is third on the stack.
globaldict /My_working_Dict get %% get My_working_dict from globaldict (leaves My_working_dict on the operand stack
/PageCount get %% get PageCount from the dictionary on the stack
256 string %% Temporary string to hold the count
globaldict /My_working_Dict get %% get My_working_dict from globaldict (leaves My_working_dict on the operand stack
/PageCount get %% get PageCount from the dictionary on the stack
exch
cvs %% Convert the top object on the stack into a string, storing the result in the second object down, whic must be a string
show %% draw the string on the page using the current colour and font.
true
}
{
pop
false
} ifelse
}
>> setpagedevice
我已经通过柔软的示例进行了尝试,并且对我有用。