我在本地 PDF 打印 (CUPS) 与 Google 云打印之间存在质量问题。 (GCP 更好,使用 CUPS 我会得到错误的大小、错误的字符、错误的字体。所以我想知道 CUPS 是做什么的!)
打印机本身可以处理多种格式:application/pdf (≥ 1.0, ≤ 1.7)、image/jpeg、image/tiff、image/pwg-raster
几个月来,我以不同的方式将打印机添加到 CUPS,我还使用它“无驱动”,其中 CUPS 检测本地网络本身中的打印机。
在所有情况下,打印 PDF 时都会出现错误;不完全是这样,但印刷品对我来说毫无用处。发生了什么:页面放大了约 30%,从第 2 或第 3 页开始,字体混合在一起,字符变成符号,段落以粗体打印,等等......
如果在同一台打印机上通过 Google 云打印打印相同的 PDF,效果会非常好。直接将 PDF 发送至 USB 记忆棒打印机也同样很棒。 – 我希望从我的计算机打印得到同样好的结果!
我的问题是:
- 我想知道每台 CUPS 打印机在发送到真正的打印机之前在我的机器上采用什么管道。它检测格式吗?如何?它会再次重新转换为 PDF 吗?它将使用哪种 PPD?管道还采取哪些其他决策以及进行哪些转换?
- 我想从已通过的打印作业中了解:CUPS 检测到了什么?它做了哪些转换?我在哪里可以获取生成的中间输出?
到目前为止,我没有发现 CUPS 调试/逆向工程的良好切入点(使用我的心中的疑问)...
答案1
我只回答你的部分问题,因为你似乎拥有敏锐的头脑,只需要展示一些隐藏的钩子就可以爬上墙壁:
“它将使用哪种 PPD?”
如果一个打印队列
printername
是本地安装的(如果它不是“原始”队列),它将使用 PPD/etc/cups/ppd/printername.ppd
。“它能检测格式吗?如何检测?”
是的,它确实。当您启用调试日志记录时(行
LogLevel debug
在/etc/cups/cupsd.conf),你会看到一行错误日志阅读“自动输入文件……”。 (如果作业已经声明了哑剧类型,则不会自动键入,例如lp -d printername -o document-format=application/pdf my.pdf
.)各种 MIME 类型的分类规则定义在/usr/share/cups/mime.types以及可能与后缀位于同一目录中的所有其他文件*.类型。 (您也可以在那里放置您自己的规则,以定义您自己的自定义 MIME 类型,这些类型应由您自己的自定义过滤器处理......)
“管道还做出哪些其他决定以及进行哪些转换?”
如果 PPD 没有任何以其中之一开头的行
*cupsFilter:
或者cupsFilter2:
关键字,则假定最终打印设备是 PostScript 打印机。因此,它将所有内容转换为 PostScript,而不会作为 PostScript 提交。如果有一行或多行以关键字开头
*cupsFilter:
或者*cupsFilter2:
它将从这些行中读取打印设备可以使用的 MIME 类型,并将采用适当的过滤器链来生成相应的 MIME 类型。可以处理某些 MIME 类型的过滤器列于/usr/share/cups/mime.convs以及可能与后缀位于同一目录中的所有其他文件*.转换。 (您可以将自己的自定义过滤器放在那里,用于您想要由这些过滤器处理的任何 MIME 类型...)
这*.转换文件命名了相应过滤器可以使用和生成的输入和输出 MIME 类型,以及这种转换将导致的虚拟“成本”(只是一个整数)。当面对 CUPS 可以构建的不同可能的过滤链时,它会
application/alpha
选择application/zeta
总成本最低的一个。
“它会再次重新转换为 PDF 吗?”
很可能不会。除非您要求将打印选项用于需要它的原始 PDF:仅打印一系列页面;在一张纸上打印 2 页或更多页;缩放它;重新排列页面以进行小册子打印等。然后
pdftopdf
可以应用过滤器,将其转换为application/pdf
到application/vnd.cups-pdf
。“CUPS 检测到了什么?”
参见上文:在中搜索字符串“自动键入文件”
/var/log/error_log
:sudo grep -A 2 "Auto-typing file" /var/log/error_log
“它做了什么转换?”
参见
error_log
再次并搜索包含的行Started filter
:sudo grep "Started filter" /var/log/error_log
“我在哪里可以获取生成的中间输出?”
您不能直接执行此操作。您必须操作 CUPS 的每个过滤器才能写出中间格式。 (我能去做吧,我有一个现成的食谱,但你必须付钱给我才能应用它。)
因此,获取中间输出可能超出了您的范围,您可以做一些不同的事情:模拟过滤链CUPS 会雇用任何工作。
您可以通过阅读手册页来了解如何执行此操作
cupsfilter
。您还可以仅列出 CUPS 将用于任何打印队列的过滤器:cupsfilter \ --list-filters \ -d <printername> \ -i <inputmime/type> \ -m <outputmime/type> \ -o "number-up=4 page-ranges=3-5,7,11" \ <filename>
答案2
您的问题没有指定您正在使用的操作系统。我的答案是针对 Debian 9.6 和网络连接的 Kyocera FS-1350DN,指定用于处理“PDF 直接打印”。那里应该cups 没有必要篡改 PDF 文件。
要找到答案,您必须启用 cups 调试。不幸的是,cupsctl --debug-logging
(作为 root)失败并出现错误消息cupsctl: Forbidden
。在文件 /etc/cups/cupsd.conf 中设置LogLevel debug
并重新启动 cupsd 后,我发送了一个带有lpr scale.pdf
.该文件包含来自 CAD 程序的线条图形(无灰度)并以 100% 比例打印。
/var/log/cups/error_log 中的相关行(总共 300 行)如下:
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] Request file type is application/pdf.
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] 3 filters for job:
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftopdf (application/pdf to application/vnd.cups-pdf, cost 66)
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftops (application/vnd.cups-pdf to application/vnd.cups-postscript, cost 100)
D [11/Dec/2018:17:50:02 +0100] [Job 319] - (application/vnd.cups-postscript to printer/fs1350, cost 0)
⋮
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter /usr/lib/cups/filter/pdftopdf (PID 16570)
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter /usr/lib/cups/filter/pdftops (PID 16571)
I [11/Dec/2018:17:50:02 +0100] [Job 319] Started backend /usr/lib/cups/backend/socket (PID 16572)
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] pdftops - copying to temp print file \"/tmp/040bb5c158ce7\"
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16570 (/usr/lib/cups/filter/pdftopdf) exited with no errors.
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] 319 h scale.pdf 1 \'finishings=3 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf\'
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] Running command line for gs: gs -q -dNOPAUSE -dBATCH -dSAFER -dNOMEDIAATTRS -sDEVICE=ps2write -sOUTPUTFILE=%stdout -dLanguageLevel=3 -r1200 -dCompressPages=false -dCompressFonts=false -dNoT3CCITT -dNOINTERPOLATE -c \'save pop\' -f /tmp/040bb5c158ce7
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter gs (PID 16577)
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started post-processing (PID 16578)
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] Started filter pstops (PID 16579)
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] %!PS-Adobe-3.0
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%BoundingBox: 0 0 595 842
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%HiResBoundingBox: 0 0 595.00 842.00
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%Creator: GPL Ghostscript 920 (ps2write)
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%LanguageLevel: 2
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%CreationDate: D:20181211175002+01\'00\'
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%Pages: 1
D [11/Dec/2018:17:50:02 +0100] [Job 319] %%EndComments
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16577 (gs) exited with no errors.
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16578 (Post-processing) exited with no errors.
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16579 (pstops) exited with no errors.
⋮
D [11/Dec/2018:17:50:02 +0100] [Job 319] PID 16571 (/usr/lib/cups/filter/pdftops) exited with no errors.
⋮
包含的行- (application/vnd.cups-postscript to printer/fs1350, cost 0)
告诉您cups正在使用后处理器(也称为打印机驱动程序)/etc/cups/ppd/fs1350.ppd。使用 - 命令可以获得同一进程的另一个视图ps
。一个摘抄的输出
while true ; do date +'%N'>> log; ps axSfu | fgrep -v grep | egrep '^lp[[:space:]]|/usr/sbin/cupsd' >> log ; done
这是
⋮
root 15796 0.1 0.1 171440 8536 ? Ssl 17:49 0:00 /usr/sbin/cupsd -l
lp 16571 0.0 0.0 77632 5728 ? S 17:50 0:00 \_ fs1350 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp 16577 0.0 0.2 129760 20836 ? R 17:50 0:00 | \_ gs -q -dNOPAUSE -dBATCH -dSAFER -dNOMEDIAATTRS -sDEVICE=ps2write -sOUTPUTFILE=%stdout -dLanguageLevel=3 -r1200 -dCompressPages=false -dCompressFonts=false -dNoT3CCITT -dNOINTERPOLATE -c save pop -f /tmp/040bb5c158ce7
lp 16578 0.0 0.0 77632 924 ? S 17:50 0:00 | \_ fs1350 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp 16579 0.0 0.0 75424 5288 ? S 17:50 0:00 | \_ fs1350 319 h scale.pdf 1 finishings=3 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
lp 16572 0.0 0.0 79792 5900 ? S 17:50 0:00 \_ socket://fs1350.xxxx.xxxx.xxx 319 h scale.pdf 1 finishings=3 number-up=1 job-uuid=urn:uuid:045216b6-e2e0-34ee-50af-36c3bdbdc04f job-originating-host-name=192.168.0.2 date-time-at-creation= date-time-at-processing= time-at-creation=1544547002 time-at-processing=1544547002 document-name-supplied=scale.pdf
⋮
告诉我们cups
调用预过滤器(pdftops,PID 16571,此处名为 fs1350)和后端(PID 16572,此处名为 socket://fs1350.xxxx.xxxx.xxx)。预过滤器调用gs
.由于整个处理时间不到 0.2 秒,因此将输出收集到文件中是有意义的。只是date +'%N'
为了了解时间安排。
明显的不必要的缩放(我在评论中写到)是evince→Print→Print Setup→Scale→100%
因为默默地被覆盖经过evince→Print→Page Handling→Fit to Printable Area
。因此,请务必仔细检查您的打印客户。
唉,这还不是故事的全部。为了绕过cups并使用打印机的“PDF直接打印”功能,我直接发送了文件:nc fs1350.xxxx.xxxx.xxx 9100 < scale.pdf
.经过 10 多分钟的处理时间后,打印机将纸张发出。
使用 netcat 进行原始打印,数字反映尺寸(以毫米为单位)。
使用 lpr→cups 打印输出
文件的位图图像 (1200 dpi)
无论打印机设置如何“覆盖 A4/LT”,原始打印的缩放比例均为 97.7%,而 lpr→cups 打印的缩放比例则正常。原始打印的网点增大较小,而 lpr→cups 打印的网点增大则有点微薄。
缩小之前绘图的页面尺寸生的印刷扩大了规模。
答案3
让我在这里补充一下...我正在运行带有 CUPS 2.3.3op2 的 Gentoo Linux,通过 IPP Everywhere 将作业发送到 Xerox VersaLink C405。该打印机本身支持 PostScript(真正的 Adobe PostScript 3,而不是仿真)以及 PDF、PCL6、PCL5e 和 XPS。
从日志中的调试信息来看,CUPS 正在将 PostScript 发送到机器,无论输入格式如何。这是我在将 PDF 数据通过管道传输到时看到的情况lp
(为了可读性而删除了日期):
[Job 61] 3 filters for job:
[Job 61] pdftopdf (application/pdf to application/vnd.cups-pdf, cost 66)
[Job 61] pdftops (application/vnd.cups-pdf to application/vnd.cups-postscript, cost 100)
[Job 61] - (application/vnd.cups-postscript to printer/vlc405, cost 0)
如果您想将 PDF 直接发送到打印机,您可以完全绕过 CUPS,并使用 netcat 将数据直接发送到打印机上的端口 9100(假设已启用):
nc 192.0.2.0 9100 < file.pdf
(将 IP 地址替换为您的打印机的 IP 地址。)
如果您的机器不直接支持 PostScript 或 PDF,则此方法不适用。正版 Adobe PostScript 3 支持通常仅限于办公用途的高端激光打印机。消费级打印机可能会使用 PWG Raster 或 PDF 来实现 IPP Everywhere。有些模仿了 PostScript 3,这可能不太可靠。 (经常使用仿真,因为 Adobe 参考实现的许可费用昂贵。)