PostScript 常见问题解答/使用 PostScript
在以下几种情况下,PostScript 打印机是理想的选择:
- 你需要打印包含已放置 EPS 文件的文档
- 你从第三方接收打印作业,并且需要可移植的 页面描述语言
- 你期望打印可变内容文档
- 桌面打印机充当更昂贵的打印机或图像设定器的廉价校样机
- 矢量页面描述比页面栅格图像要短得多
- 你运行的是 类 Unix 系统,其中 PostScript 语言充当打印机 API。
带有非 PostScript 打印机的软件 RIP 正在成为 PostScript 打印机的一个很好的替代方案。与内置的 RIP 不同,软件和硬件可以轻松升级。主机操作系统还提供了更好的调试环境。
PostScript 是一种低级的 页面描述语言。PostScript 图形模型基于表示元素:线条、曲线、字符、图像。它没有单词、段落、对齐、脚注等概念。大多数作者更喜欢在更高层次上工作,并从高级页面描述生成表示格式(PostScript、PDF、PCL 等)。
TeX 是一种排版程序,专为高质量地编排包含大量数学和技术表达式的材料而设计。它已被许多作者和出版商采用,他们用来生成技术书籍和论文。它是由斯坦福大学的唐纳德·克努斯教授创建的,最初是为了准备他的书籍系列《计算机程序设计艺术》。
groff(GNU troff)软件是一个排版软件包,它读取混合有格式化命令的纯文本并生成格式化的输出。
在 Mac OS 和 Microsoft Windows 上的 PostScript 打印机驱动程序可以从传入的 GDI 调用生成 PostScript 文件。因此,所有可以打印的应用程序也可以生成 PostScript。但是,文件中的图形原语集将受到 GDI 图形模型的限制。大多数图形编辑器和 DTP 应用程序绕过 GDI 并直接生成 PostScript。这有助于生成更好的 PostScript,并为应用程序提供更灵活的图形模型。
有时,需要手动创建或修改 PS 文件。PostScript 文件可能很大,并且包含二进制数据。文本编辑器不应该扩展制表符或标准化行尾。emacs 是一个不错的选择,因为它可扩展并且包含 PostScript 主模式。
在类 Unix 系统上,你可以使用 lpr
lpr -S computer_name -P queuename filename.ps
在 Microsoft Windows 上,你可以将文件发送到打印机,如下所示:
copy /b filename.ps lpr1
或
copy /b filename.ps \\computer_name_or_ip\printersharename
一些打印机也支持 lpr 协议。
PrintFile 是一个免费的 GUI Windows 程序,它将文件复制到系统打印队列。它也可以从符合 DSC 的 PostScript 文件中选取页面。
在 Classic Mac OS 上,你可以将文件拖放到打印机图标上。
PostScript 文件是为顺序打印而设计的 - 图像通常存储为内联流,页面大小和分辨率是页面描述的一部分。
查看器应该以随机顺序和放大倍数浏览文档。这可以通过将 PostScript 转换为内部形式来实现,该内部形式允许直接访问页面元素,并快速裁剪不可见的物体。没有一个 PostScript 查看器以这种方式工作。
GSview 是由 Ghostgum Software 的 Russel Lang 开发的 Ghostscript 的免费图形界面。页面选择是通过 DSC 处理实现的;缩放是通过重新解释页面实现的。GSview 可用于 Win32、Win32s、OS/2 和 GNU/Linux。旧版本可用于 Win16。还有其他用于 Ghostscript 的图形 X 窗口前端 - 例如 mgv、Moonshiner 和 Okular。
PostScript 可以使用 Ghostscript、ps2pdf 在线、Distiller、PDFCreator 和其他几个程序轻松转换为 PDF。与 PS 查看器相比,PDF 查看器要多得多。此外,PDF 查看器通常比大多数 PS 查看器更友好,因此查看 PS 文件最方便的方法是先将其转换为 PDF 文件。最流行的免费 PDF 查看器是 Adobe Reader、Evince、Foxit Reader、MuPDF、Okular、PDF-XChange Viewer、Sumatra PDF 和 Xpdf。
许多网络打印机不接受包含二进制数据的 PS 文件。
有时不可能将文件重新创建为 7 位 ASCII,但任何文件都可以轻松地转换为 ASCII 流,并通过相应的解码过滤器执行。以下脚本将标准输入转换为十六进制流,并添加解码代码。所有 DSC 注释都将被隐藏,但大多数打印机都会忽略它们。该脚本在 bash 和 GNU/Linux 系统上进行了测试。
#! /bin/sh
echo '%!'
echo 'currentfile /ASCIIHexDecode filter cvx exec'
od -A n -v -t x1
echo '>'
MS-DOS 和 Windows 的脚本版本必须从自身中读取 '>'
字符,因为 echo ">"
打印 ">"
(带引号)。
@echo off
rem ">"
echo %%!
echo currentfile /ASCIIHexDecode filter cvx exec
od -A n -v -t x1
od -A n -v -t c -j 16 -N 1 %0
od
(八进制转储)来自 GNU Textutils 包。它在所有默认的类 Unix 系统(包括 macOS)上可用,并且可以使用 Cygwin 或 MinGW 包在 Windows 上安装。
PostScript 实用程序可以使用 PostScript 语言轻松编程。以下程序读取输入文件或标准输入,压缩它,可选地使用 ASCII85 编码进行转换,然后写入输出文件或标准输出。该程序由 Ghostscript 运行,使用:
gs -q [-dASCII] [-dLEVEL3] -- encode.ps [INFILE [OUTFILE]]
其中
-q
禁止将版权信息写入 stdout-dASCII
选择 ASCII85 编码-dLEVEL3
选择在 3 级中引入的 Flate 编码encode.ps
是程序INFILE
是输入文件,默认为 stdinOUTFILE
是输出文件,默认为标准输出。
%!
% encode.ps - compress and encode PS file to reduce upload time.
% This won't work if the file contains multiple jobs separated by ^D
%
/stderr (%stderr)(w) file def
/error { stderr exch writestring } bind def
/closetarget <</CloseTarget true>> readonly def
%
/openfile % fname mode -> file
{ { file } stopped
{ exch (Cannot open file: ) error error (w) eq { (for writing\n) } { (for reading\n) } ifelse error
flush quit
}
if
} bind def
%
/main % - -> -
{ mark shellarguments
{ counttomark 2 le
{ counttomark
{ { (%stdin)(r) file (%stdout)(w) file }
{ (r) openfile (%stdout)(w) file }
{ (w) openfile exch (r) openfile exch }
}
exch get exec dup % input output output
//systemdict /ASCII .knownget dup { true eq and } if
{ //closetarget /ASCII85Encode filter
(/ASCII85Decode filter)
}
{ () }
ifelse
exch % input output () output
//systemdict /LEVEL3 .knownget dup { true eq and } if
{ //closetarget /FlateEncode filter exch
(/FlateDecode filter)
}
{ //closetarget /LZWEncode filter exch
(/LZWDecode filter)
}
ifelse
concatstrings % input output output ()
2 index (%!\ncurrentfile) writestring
2 index exch writestring
exch ( cvx exec\n) writestring
exch 61440 string % output input buf
{ 3 copy readstring pop % output input buf output buf
dup () eq { pop pop exit } if
writestring
}
loop
pop closefile closefile false
}
{ (Incorrect number of file name arguments.\n) error true
}
ifelse
}
{ (Missing '--' preceding encode.ps\n) error true
}
ifelse
{ (Usage: gs -q -dASCII -dLEVEL3 -- encode.ps INFILE OUTFILE\n) error flush
}
if
} bind def
%
main clear quit
如果需要,可以在将文件下载到打印机之前进行 DSC 处理。开发一个基于 ASCII85 的 DSC 感知转换器留给读者作为练习。
封装 PostScript,或 EPS 文件,通常用于包含在可打印的 PostScript 或其他 EPS 文件中。与可打印的 PostScript 不同,它们可能具有
showpage
运算符未包含- 图像移出可打印区域
- 图像大小过大或过小
- PC 风格的标题和预览
因此,直接将 EPS 文件发送到 PostScript 打印机可能会导致 PostScript 错误或仅打印页面。
标准方法是在图形设计应用程序中将 EPS 放置在页面中,然后打印。
为了直接打印 EPS 文件,您需要添加一个 PS 标题,它将执行所有必要的调整。
cat header.ps file.eps | lpr
在 net.anastigmatix.Import 资源页面上给出了一个合适的标题作为示例。
将文件发送到 PostScript 解释器。如果您喜欢结果,则该文件有效。PostScript 解释器包括
- 任何 PostScript 打印机
- Ghostscript
- Acrobat Distiller
- 显示 PostScript
当然还有其他的,但这些是最简单/最便宜的获取方式。
事实上,这将只检查 PostScript 程序在经过测试的解释器上的正确性。不同的解释器提供非常不同的执行环境,这会使 PS 程序采用不同的分支。
PostScript 程序可能会产生意外的输出,而不会报告任何 PostScript 错误。在关键任务情况下,必须在激光打印机上打印并由设计人员签署的校样。
使用 bbox 设备解释文件并计算 HiResBoundingBox 行。
gs -q -dNOPAUSE -dBATCH -sDEVICE=bbox foo.ps 2>&1 | grep -c HiResBoundingBox
命令也比较快
yes | gs -q -dBATCH -sDEVICE=nullpage foo.ps | grep -c showpage
假设文档符合 DSC,可以直接在文档中计算 %%Page 注释。
grep -c %%Page: file.ps
首先,您需要决定是什么使页面成为彩色页面。可能,单色页面在 CMY 分量的密度为零。要使用 Ghostscript 检查这一点,您需要选择一个真彩色 CMYK 设备,安装正确的 CRD 并光栅化文件。
如果任何像素在 CMY 平面中具有非零分量,则该页面为彩色页面。
DSC(文档结构约定)旨在提供一种简单的方法来解析 PostScript 文档,重新排列页面,添加缺失的字体,替换图像等。虽然大多数程序生成 DSC 注释,但很少有程序使用它们。看来,即使是主要供应商也从未测试过 DSC 注释的正确性。
有时,声称 DSC 符合性的文档在修改后会因 PostScript 错误而失败。更糟糕的是,页面可能会以某种微妙的方式损坏。例如,可增量下载字体的某些字符可能会被静默替换为默认字符。
基于 DSC 注释的页面选择由 PrintFile 和 GSview 使用。
PDF 可以作为一种方便的中间格式,尤其是在多次执行页面提取时。您可以使用 Ghostscript 将文件转换为 PDF 并提取一定范围的页面,如下所示
ps2pdf input.ps output.pdf
gs -dFirstPage=1 -dLastPage=2 output.pdf
偶尔,其他图形格式可能比 PDF 效果更好。作者曾经编写了 bilist.cpp
,将两个 A5 页面放在一张 A4 页面上,并将页面重新排列为一些旧 PCL 打印机的签名。
有几种方法可以解决这个问题。每种方法都有其优点。
直接操作保留了大多数 PS 结构,并且占用最少的处理器时间。不幸的是,它仅适用于符合 DSC 的 PostScript 文件。虽然大多数主流应用程序生成的 DSC 文件声称符合 DSC,但很少有文件经过这样的测试。例如,Microsoft PS 驱动程序默认情况下会生成不符合规范的文件。
来自 psutils 的 psselect
可以选择和重新排列符合 DSC 的 PS 文件中的页面。
转换为光栅图像是一种简单可靠的方法。例如,bilist.cpp
从 PCL 文件中提取页面,将页面重新排列为签名,并将它们放置成两页一页。Ghostscript 可用于 PostScript 到 PCL 的转换。
转换为 PDF 极大地简化了进一步的文档处理。PDF 文件中的页面可以以任何大小或顺序提取和打印。PostScript 文件可以使用多种应用程序转换为 PDF。例如,Ghostscript
ps2pdf input.ps output.pdf
要从 PDF 文件中提取一定范围的页面到另一个 PDF 文件,请使用
ps2pdf -dFirstPage#111 -dLastPage#666 input.pdf output.pdf
要从 PDF 文件中提取一定范围的页面并转换为 PS 文件,请使用
ps2ps -dFirstPage#111 -dLastPage#666 input.pdf output.ps
将 PDF 文件连接起来始终很安全,如下所示
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=file.pdf \
-c save pop -f file1.dsc file2.dsc file3.dsc ...
以上方法足以以任何顺序重新排列页面,但复杂的工作可以更有效地完成。PDF 文件可以转换为简单的符合 DSC 的 PS 文件。
pdf2dsc source.pdf output.dsc
输出文件将非常简单,因为所有复杂性都隐藏在 Ghostscript 库中。使用任何 DSC 实用程序、文本编辑器或脚本都很容易修改格式。
%!PS-Adobe-3.0
%...
/Page null def/Page# 0 def/PDFSave null def/DSCPageCount 0 def
/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def
GS_PDF_ProcSet begin pdfdict begin
file.pdf) (r) file { DELAYSAFER { .setsafe } if } stopped pop
pdfopen begin
%%Page: 1 1
1 DoPDFPage
%%Page: 2 2
2 DoPDFPage
%%Trailer
currentdict pdfclose end end end
%%EOF
更新后的文件可以转换回 PDF。
ps2pdf source.dsc result.pdf
DSC 文件使用 GS 库,如果 DSC 文件仅提供给 Ghostscript,则效果很好。要生成可移植的 PS 文件,请将其转换回 PS。
当驱动程序为单色打印机生成 PostScript 流时,它通常会将彩色图像转换为灰度,以实现更好的传输时间、更快的渲染和更低的资源使用。将矢量对象转换为灰度不会节省太多空间或时间。因此,驱动程序将其留给 PostScript 解释器。
当作业打印到通用 PostScript 打印机驱动程序时,这个问题经常发生。通用驱动程序不是最好的驱动程序。它仅限于大多数打印机上可用的 PostScript 语言的通用子集。它是单色的,只有少量介质、字体选择,没有特殊功能。来自通用驱动程序的 PostScript 文件将在多种打印机上打印,但许多功能将缺失。
虽然看起来每台打印机都使用特殊的驱动程序,但实际上是同一个驱动程序配置用于不同的打印机。驱动程序从 PPD 文件中获取配置参数。如果可能,应使用本机 PPD 文件。Acrobat Distiller PPD 是生成不包含特定于供应商的功能的彩色 PostScript 文件的不错选择。
对页面进行光栅化并将页面重新组合到复合文件非常简单。光栅化可以在每平面 8 位或每平面 1 位进行,具体取决于是否需要对复合图像进行任何颜色校正。
在矢量级别合并平面要困难得多。为此工作的唯一已知工具是来自 Creo(现已停产且不受支持)的 Seps2Comp Acrobat 插件。可以使用包括 Ghostscript 和 Acrobat Distiller 在内的许多程序将 PostScript 文件转换为 PDF。
Windows 驱动程序在进行 N-up 打印时会在虚拟页面周围生成黑框。这些框是在 `nupshowpage` 过程中绘制的。要删除这些框,必须修改此过程。在 3 级解释器上,`Hack-MSDriver-n-up` `IdiomSet` 可以在解释器加载作业文件时识别并替换此过程。不需要修改作业文件。要激活替换,需要将 idiom 文件复制到打印机或基于主机的解释器上的 `/Resource/IdiomSet/` 目录中。基于主机的解释器上的 PostScript 根目录可能与系统根目录不同。对于一次性替换,您也可以将 `IdiomSet` 文件附加到作业文件前面。
对于 1 级和 2 级解释器,必须使用任何文本编辑器从作业文件本身中删除 `framenup { ... } if` 片段。
%!PS-Adobe-3.0
%%Title: Hack-MSDriver-n-up
% Remove black frame around n-up pages generated by MS Driver
%%VMusage: 0 0
%%VMlocation: global
%%EndComments
%%BeginResource: IdiomSet Hack-MSDriver-n-up
currentuserparams /IdiomRecognition get
<</IdiomRecognition false>> setuserparams
currentglobal true setglobal
/Hack-MSDriver-n-up
<< 8 dict begin
/; /grestore load def
/V /div load def
/@ /dup load def
/~ /exch load def
/rs /rectstroke load def
/! /pop load def
/? /ifelse load def
/+ /translate load def
/nupshowpage
[ { ; $m concat
framenup
{ pagemarg_nup 2 V nups V
@ $m idtransform abs neg ~ abs neg ~
paperw_nup paperh_nup rs
}
if
/pgx_nup pgx_nup 1 add
@ nx_nup eq
{ ! 0 store paperw_nup 1 nx_nup sub mul
/pgy_nup pgy_nup
1 add @ ny_nup eq
{ ! 0 store paperh_nup 1 ny_nup sub mul
}
{ store paperh_nup
}
?
}
{ store paperw_nup 0
}
? + $m matrix invertmatrix concat startpage
} bind
{ ; $m concat
/pgx_nup pgx_nup 1 add
@ nx_nup eq
{ ! 0 store paperw_nup 1 nx_nup sub mul
/pgy_nup pgy_nup
1 add @ ny_nup eq
{ ! 0 store paperh_nup 1 ny_nup sub mul
}
{ store paperh_nup
}
?
}
{ store paperw_nup 0
}
? + $m matrix invertmatrix concat startpage
} bind
]
end
>> /IdiomSet defineresource pop
setglobal <</IdiomRecognition 3 -1 roll>> setuserparams
%%EndResource
%%EOF
待写。
该文档可以被缩放或只是移动。
psresize -PA4 -pletter a4.ps letter.ps
psnup -pletter -Pa4 a4file.ps letterfile.ps
修复页面设备,策略 3。
PostScript 文档中的图形通常作为 EPS 文件包含,可以使用文本编辑器轻松提取。在符合 DSC 的文档中,EPS 文件使用文本编辑器进行封装。
%%BeginDocument
...
%%EndDocument
不要忘记 EPS 文件可以嵌套。
从 PostScript 文件中提取的 EPS 文件没有预览,可以使用 Ghostscript 重新生成预览。
如果您能运行 Perl,请查找 `bw_convert`,这是一个微小的 Perl 脚本,它将 PostScript 文件中的每个 RGB 颜色声明更改为黑色或灰色值。简单来说,它将 "setrgbcolor" 替换为 "pop pop pop 0 setgray"。可以在 bw_convert 中找到该脚本。该网站上没有记录脚本作者。然而,这个脚本实际上是一个关于如何不做事的绝佳例子;作者并没有真正理解 PostScript 是一种编程语言,简单的词法更改往往会失败,而在一开始添加一行额外的代码会更有效。该脚本也不处理图像、CMYK 数据或 2 级颜色运算符。
可以通过在 PostScript 文件开头添加以下行来完成类似的操作
/setrgbcolor {0.11 mul 3 1 roll 0.59 mul 3 1 roll 0.30 mul add add setgray} def
它将覆盖 `setrgbcolor` 并使用 `setgray` 计算灰度颜色。但这不会影响图像,也可能不会改变您想要更改的所有内容。也可能存在其他问题,因此不保证结果。
3 级 PostScript 有一种强大的方法可以微调设备相关颜色到设备无关颜色的校正:`UseCIEColor` 页面设备键和 `DefaultGray、DefaultRGB、DefaultCMYK` 颜色空间。
当 `UseCIEColor` 标志打开时,灰度、RGB 和 CMYK 颜色被解释为 `DefaultGray`、`DefaultRGB` 和 `DefaultCMYK` 颜色空间中的颜色。鲜为人知的是,设备颜色空间的数组形式(例如 `[DeviceCMYK]`)可以被定义为 `Default*` 资源,有效地禁用相应的转换。
CMYK 到设备无关颜色的转换通常是不希望的,因为会导致黑色生成信息的丢失。
对日期和时间的内置访问是通过 `currentdevparams` 和 `setdevparams` 在 `%Calendar%` 设备上进行的,该设备出现在 PostScript 语言参考手册 2012 版补充说明 中,用于 PostScript 语言级别 2。以下代码将日期和时间写入标准输出
(%Calendar%) /IODevice resourcestatus {
pop pop (%Calendar%) currentdevparams
dup /Running get {
dup /Year get 4 string cvs print (-) print
dup /Month get 2 string cvs print (-) print
dup /Day get 2 string cvs print ( ) print
dup /Hour get 2 string cvs print (:) print
dup /Minute get 100 add 3 string cvs 1 2 getinterval print (:) print
/Second get 100 add 3 string cvs 1 2 getinterval print (\n) print
} {
(Clock/calendar is present but not running.\n) print
} ifelse
} {
(No clock/calendar present.\n) print
} ifelse
该标准没有提供时区信息,时钟通常设置为本地时间。它的范围扩展到 2079 年。如果解释器在主机操作系统上运行,则操作系统可能会确定 `setdevparams` 是否能够真正设置时钟。
基于主机的 PostScript 解释器可以访问文件系统,包括命名管道和设备,因此可能性是无限的。这个例子是在 GNU+Linux 上使用特定解释器 Ghostscript 测试的。
在一个终端上键入以下内容
mkfifo foo
while true; do date >foo; done
在同一目录中的另一个终端上运行 `gs -dNODISPLAY`,然后键入
/t { (foo)(r) file closefile (foo)(r) file dup
28 string readstring pop = closefile} def
现在,在 Ghostscript 提示符下键入 `t` 会显示当前时间,使用主机操作系统的 `date` 命令而不是 `%Calendar%` 设备。
PostScript 已被用来实现一个 HTTP 服务器。