关于打印:我或许应该知道些什么?

关于打印:从刻板雕字到百家争鸣的格式混战


第一回:老祖宗的智慧——把信息"压"到纸上

要说打印这事儿,还真得从咱们老祖宗说起。

隋唐年间,中国人发明了雕版印刷。工匠们把一整页文字反刻在一块木板上,刷上墨,往纸上一压——得,一页书就出来了。这个思路朴素至极:你想让纸上出现什么图案,就做一个对应的"模子",然后转印上去。 这个思路,穿越一千多年,到今天的激光打印机里,本质上没变过。激光打印机的感光鼓就是那块"板",激光束就是那把"刻刀",碳粉就是那层"墨"。

但雕版有个大问题——一块板只能印一页。你要印一本三百页的书,就得刻三百块板,费时费料。于是北宋年间,毕昇想出了活字印刷:把每个字单独做成一个小方块,要印什么页就把字排进框里,印完了拆开,下次换个内容重新排。

这里头有个关键的东西被发明了出来,那就是 “排版” 这个概念。你不再是直接画一整页的图,而是用一个个标准化的小零件(活字)按照一定的规则(行距、字距、边距)组合成页面。汉字的方块字结构在这里体现出巨大优势——每个字占一个固定大小的格子,排起来整整齐齐,计算位置非常简单。

记住这个概念:把内容拆成标准化的小元素,然后按规则排列。 这就是排版的本质,也是后来所有页面描述语言想要解决的核心问题。


第二回:电脑时代开幕——最笨的打印方式

时间快进到 20 世纪中叶,计算机诞生了。最早的计算机打印机叫行式打印机(Line Printer),简称 LP。Linux 里 lplpr 命令的名字就来源于此。这种打印机有多简单呢?电脑发过去一个字符编码,打印机查一下自己内置的字模表,把对应的字打到纸上。你发个 “A”,它就打个 A。你发个换行符,它就滚一行纸。

这个时代没有什么"格式"可言。电脑和打印机之间传的就是纯 ASCII 文本——一串字符编码。打印机是个"会写字的打字机",仅此而已。你只能打纯文本,什么字体、字号、加粗斜体、图片、表格,统统不存在。排版?不存在的。

后来出现了点阵打印机(Dot Matrix Printer),比如爱普生(Epson)在 1970 年代末推出的打印机。点阵打印机的打印头有一列针,通过控制哪些针击打色带,可以在纸上打出由点组成的字符和简单图形。爱普生为了控制自家打印机,发明了 ESC/P(Epson Standard Code for Printers)——一套控制指令集。你在文本流里插入特殊的转义序列(以 ESC 字符开头),就能告诉打印机"切换到粗体"“把字号改成 12 磅”“移动到页面的第 3 英寸位置”。

ESC/P 是历史上第一批"打印机控制语言"之一。它很简单,基本上就是"移动到哪里、用什么样式、打什么字符"这种逐行指令。它能做一些基本的排版了,但依然很原始——你没法画一条精确的贝塞尔曲线,没法旋转一个文字,没法在页面上精确地放一张图。


第三回:激光打印时代——两大宗师登场

1980 年代初,一项划时代的技术成熟了:激光打印。施乐(Xerox)在 1970 年代发明了激光打印原理,但真正把它做成个人和办公产品的,是两家后来统治打印江湖数十年的公司——惠普(HP)苹果(Apple)(背后站着 Adobe)。

这两家走了两条完全不同的技术路线,由此开启了打印格式百家争鸣的时代。

惠普的路线:PCL——实用主义的工程师思维

1984 年,惠普推出了 HP LaserJet,这是历史上第一台真正意义上的桌面激光打印机。为了控制这台打印机,惠普设计了 PCL(Printer Command Language)

PCL 的设计哲学非常惠普——务实、高效、够用就好。PCL 本质上是 ESC/P 思路的升级版:还是用转义序列来控制打印机,但指令集大大丰富了,支持了光栅图形、多种字体、页面定位等功能。PCL 5 引入了矢量图形支持(HP-GL/2,这是惠普绘图仪语言的衍生),使得 PCL 能够描述比较复杂的页面了。

PCL 的核心特点是:指令式的、面向打印机的、高效的。它不需要打印机有很强的计算能力,很多渲染工作在主机端完成,发给打印机的数据比较紧凑。PCL 是惠普的私有语言,但因为 HP LaserJet 卖得太好了,PCL 成了事实上的行业标准——其他厂商纷纷宣称自己的打印机"兼容 PCL"。

Adobe 和苹果的路线:PostScript——优雅的艺术家思维

同一时期,Adobe 的创始人 John Warnock 和 Chuck Geschke(两人都是从施乐 PARC 出来的)搞出了一个野心大得多的东西—— PostScript

PostScript 不是一个"控制指令集",它是一门完整的编程语言。没错,它是图灵完备的,有变量、有循环、有条件判断、有函数(过程)、有栈操作。但它的特殊之处在于,这门语言的核心能力是描述页面上的图形。你可以用 PostScript 精确地说:“从坐标 (72, 720) 开始,用 12 磅 Times-Roman 字体,写下 ‘Hello World’”,或者"画一条从 (100, 200) 到 (300, 400) 的贝塞尔曲线,线宽 0.5 磅,颜色为 CMYK(0, 1, 1, 0)"。

PostScript 的革命性在于:它真正确立并普及了设备无关的标准 你写的 PostScript 程序,不管在 300dpi 的打印机上运行还是在 2400dpi 的照排机上运行,输出的页面在逻辑上是完全一样的,只是分辨率不同。这对出版行业来说是改天换地的——设计师在屏幕上看到的效果和最终印刷出来的效果可以做到一致(WYSIWYG:What You See Is What You Get)。

在 PostScript 之前,Xerox PARC 的 Interpress 语言已经实现了设备无关性。PostScript 是 John Warnock 离开施乐后对 Interpress 的改进和商业化

1985 年,苹果推出了 LaserWriter,这是第一台内置 PostScript 解释器的桌面激光打印机。配合苹果的 Macintosh 电脑和 Aldus 的 PageMaker 排版软件,掀起了桌面出版(Desktop Publishing, DTP)革命。设计师、出版社、广告公司疯狂追捧这套方案。

但 PostScript 有一个巨大的代价:打印机里必须内置一个 PostScript 解释器。这个解释器是一个小型计算机——需要 CPU 有足够的算力,需要足够的 RAM(解释一个复杂的 PostScript 页面可能需要好几兆内存,在 1980 年代那是一笔巨款)。结果就是,PostScript 打印机非常贵。苹果 LaserWriter 首发价 6995 美元,而惠普 LaserJet 是 3495 美元。而且,Adobe 对 PostScript 收取高昂的授权费。

这里就产生了打印江湖的第一道裂痕:成本。 高端市场(出版、设计、广告)选择了 PostScript,因为它精确、优雅、设备无关。低端和办公市场选择了 PCL,因为它便宜、实用、速度快。


第四回:格式战争升级——PDF 的诞生与 PCL 的进化

Adobe 的第二招:PDF

PostScript 虽然强大,但它有个问题——它太灵活了。因为是图灵完备的编程语言,同一个页面可以有无数种写法,解析和显示一个 PostScript 文件需要"执行"它,这让文件交换变得困难(你没法快速跳到第 50 页,因为你不知道前 49 页的程序执行完后栈上留下了什么状态)。

1993 年,Adobe 发布了 PDF(Portable Document Format)。PDF 可以理解为 PostScript 的"静态快照版"——它继承了 PostScript 的图形模型(坐标系、贝塞尔曲线、字体嵌入、色彩空间),但砍掉了编程语言的部分。一个 PDF 文件就是对页面内容的声明性描述,不是一个需要执行的程序。这使得 PDF 文件可以快速随机访问(直接跳到第 50 页),文件大小更可控,也更安全(不会有恶意 PostScript 程序在打印机里跑死循环)。

PDF 后来成了数字文档交换的事实标准,也成了打印工作流中最通用的中间格式。你今天在任何应用程序里点"打印",中间大概率会产生一个 PDF。

惠普的进化:PCL XL (PCL 6)

到了 1990 年代中期,计算机世界正经历一场深刻变革:图形用户界面(GUI)全面崛起。1995 年 Windows 95 发布,桌面操作系统彻底从命令行迈入图形时代。应用程序不再只输出简单的文本和表格,而是充斥着复杂的排版、矢量图形、嵌入式图片和丰富的字体效果。用户在屏幕上看到什么,就期望打印出来是什么——所谓"所见即所得"(WYSIWYG)。这对打印语言提出了全新的要求。

PCL 5 在文本打印领域表现出色,但它的转义序列架构本质上是为字符流时代设计的,面对 GUI 应用输出的复杂图形页面显得力不从心:数据量大、传输效率低、图形表达能力也有限。PostScript 倒是能胜任,但它毕竟是一门完整的编程语言,解释执行开销不小,而且 Adobe 的授权费也是一笔不菲的成本。

惠普看到了这个空档。1995 年,惠普推出了 PCL 6,其中的核心组件叫 PCL XL(也称 PCL 6 Enhanced)。PCL XL 是对 PCL 5 的彻底重新设计,专门面向 GUI 时代的打印需求。它抛弃了转义序列体系,转而采用紧凑的二进制流协议——用二进制操作符和属性来描述页面上的图形元素:路径、填充、渐变、图像、文字等等。这种设计带来两个显著优势:一是数据量更小、传输更快(二进制天然比文本编码紧凑);二是解析更高效,打印机处理器可以快速解码执行,不需要像 PostScript 那样运行一个完整的语言解释器。

不过,PCL XL 依然不是一门编程语言——没有变量,没有循环,没有条件判断。它的定位很明确:用最高的效率,忠实再现 GUI 应用程序的图形输出。你可以把它理解为一种高效的"图形指令录像带",忠实记录了应用程序的绘图动作,打印机只需按顺序回放即可。与此同时,PCL 6 还保留了对 PCL 5e/5c 的向后兼容(称为 PCL 6 Standard),确保老应用不会被抛弃。

到这个阶段,高端商用打印机通常同时内置 PostScript 和 PCL 两套解释器,用户可以根据需要切换——PostScript 在专业排版和设计领域依然是王者,PCL XL 则凭借效率优势在日常办公打印中占据主流。这两种语言成了打印行业的两大标准,如同江湖中的"少林"和"武当"——几乎所有正经的商用打印机都至少支持其中一种,很多高端型号则两者兼备。


第五回:穷人的打印机——GDI/Host-based 打印与私有格式的崛起

故事讲到这里,该说说低端打印机为什么那么"特殊"了。

1990 年代末到 2000 年代初,激光打印机开始向消费级市场和小型办公市场下沉。价格战打得越来越凶,厂商要把打印机做得尽可能便宜。但前面说了,PostScript 需要打印机里有一个强力的解释器(贵),PCL 虽然简单些但也需要一定的处理能力。更关键的是,传统打印机内部都有一个叫 RIP(Raster Image Processor,光栅图像处理器) 的核心组件——无论是 PostScript 还是 PCL,打印机收到的都是对页面的高层描述(“在这里画一条线”、“在那里放一段文字”),RIP 负责把这些描述计算成最终的像素点阵,告诉打印引擎每个点该不该打墨。这个 RIP 需要相当的算力和内存,是打印机硬件成本中的大头。

有人就想了一个绝妙的主意:既然用户的电脑越来越快(奔腾处理器已经很猛了),为什么还要在打印机里放一个昂贵的 RIP?让电脑把所有光栅化工作做完,把最终的像素点阵直接发给打印机,打印机只需要一个廉价的控制器把这些点"印"到纸上就行了。

换句话说,把打印机的"大脑"砍掉,让电脑的 CPU 替它思考。

这就是所谓的 Host-based 打印机(主机端渲染打印机)——打印机本身变成了一个"瘦"设备,所有繁重的页面渲染和光栅化计算都由主机(Host,也就是你的 PC)完成。在 Windows 平台上,这个渲染过程是通过操作系统的 GDI(Graphics Device Interface,图形设备接口) 子系统来实现的——应用程序的绘图指令经由 GDI 渲染成位图,再由厂商驱动转换为打印机能理解的私有光栅格式。正因如此,这类打印机在 Windows 世界里被广泛称为 GDI 打印机。这个名字既点出了它的技术实现路径,也暗示了它对 Windows 的深度依赖——离开了 Windows 的 GDI 框架,这类打印机几乎无法工作。(这也是为什么早年在 Linux 上驱动这类打印机是一场噩梦。)

这种设计的好处是打印机硬件成本暴降——不需要强力 CPU,不需要大内存来存储整页的光栅数据,不需要 PostScript 解释器的授权费,连 RIP 都省了。一台激光打印机可以卖到几百块钱,走进千家万户。

但坏处是:打印机变"笨"了。 它不懂 PostScript,不懂 PCL(或者只懂一点点残缺的 PCL),它只认识自己的私有光栅格式。这些格式是各家厂商自己定义的,本质上都是"压缩后的像素数据加上一些控制指令的包装",但每家的压缩算法不同、包装格式不同、控制指令不同。

于是乎:

三星 发明了 SPL(Samsung Printer Language),后来演变为 QPDL。SPL 把页面切成水平条带(bands),每个条带用 JBIG 压缩(一种适合黑白图像的高效压缩算法),然后打包成三星自定义的二进制格式发给打印机。

兄弟(Brother) 有自己的私有光栅格式。

佳能(Canon) 低端型号有 CAPT(Canon Advanced Printing Technology),也是一种 host-based 格式。

利盟(Lexmark) 也有类似的方案。

施乐(Xerox) 低端型号也有私有格式。

每家厂商之所以搞自己的格式而不用一个统一标准,原因是多方面的。首先是技术上的——每家的打印引擎硬件架构不同,最适合这台打印机的数据传输方式也不同,自定义格式可以做针对性的优化(比如三星的 JBIG 压缩方式特别适合其打印引擎的带状处理方式)。其次是商业上的——私有格式意味着用户必须用你的驱动,你可以通过驱动程序收集打印量数据、推送固件更新、绑定耗材(某些打印机的驱动会检测是否使用原装硒鼓)。再者是历史惯性——每家公司各自在不同时间点独立开发了自己的方案,等想到要统一的时候,各家的生态已经形成了,谁也不愿意放弃自己的格式去迁就别人。


第六回:Windows 用户无感,Linux 用户遭殃——ULD 的由来

在 Windows 上,用户对这一切是无感的。为什么?因为 Windows 有一套完整的打印架构,厂商只需要写一个 Windows 驱动程序,这个驱动程序接收 Windows GDI 或 XPS 渲染引擎的输出,转换成打印机的私有格式。Windows 的市场占有率那么高,所有厂商都会在第一时间为 Windows 写好驱动,打印机包装盒里附一张光盘(后来改成在线下载),装完驱动一切就 work 了。用户从来不需要知道什么 SPL、QPDL、PCL、PostScript——他们只知道"装个驱动就能打印了"。

但 Linux 上就是另一番景象了。

Linux 的打印系统(先是 LPD/LPRng,后来是 CUPS)是开源的、标准化的。开源社区没有办法为每一种私有格式写过滤器,因为这些格式是私有的、没有文档的、而且经常随固件版本更新。开源社区能做的是支持标准格式——PostScript 和 PCL。所以对于支持 PostScript 或 PCL 的中高端打印机,Linux 打印一直很好用。

但对于那些只认私有格式的低端 GDI 打印机,Linux 用户就傻眼了。Linux 发行版越来越多——Ubuntu、Fedora、openSUSE、Debian、统信 UOS、深度 Deepin……每个发行版的包管理方式不同、库版本不同、系统路径不同。厂商如果给每个发行版分别做驱动包,那维护成本是天文数字。

于是,ULD(Unified Linux Driver,统一 Linux 驱动) 这个概念应运而生。

ULD 的核心思路是:厂商将旗下所有(或大部分)型号打印机、扫描仪的 Linux 驱动,整合成一个统一的安装包,内含所有型号的 PPD 文件、CUPS 过滤器、扫描驱动(SANE 后端)、以及必要的共享库,通过一个统一的安装脚本自动检测系统环境、适配不同发行版。用户不需要去网上到处搜某个具体型号的 Linux 驱动——下载一个 ULD 包,跑一下安装脚本,就能覆盖这个品牌旗下一大片型号。

三星 是最早大规模推行 ULD 的厂商之一。三星的 Unified Linux Driver 覆盖了旗下几百款激光打印机和多功能一体机,里面包含了 SPL/QPDL 过滤器(如 rastertosamsungspl)、各型号的 PPD 文件、SANE 扫描后端,还附带一个图形化的打印机管理工具。这让三星打印机在 Linux 上的使用体验在同行中算是比较好的。

惠普 则有 HPLIP(HP Linux Imaging and Printing),本质上也是 ULD 的思路——一个大包覆盖惠普旗下海量型号,内含各种过滤器、PPD、扫描驱动和管理工具。HPLIP 甚至做得更彻底,它是开源的(核心部分),直接被许多 Linux 发行版预装到了系统里,所以很多惠普打印机在 Linux 上是"即插即用"的。但 HPLIP 里也有一些闭源的插件(proprietary plugin),用于支持那些使用私有格式的低端型号。

其他厂商也有类似的 Linux 统一驱动方案,虽然名称不一定叫"ULD",但思路相通:兄弟 有 Driver Install Tool 和统一的 deb/rpm 包,佳能 有 UFRII LT 驱动包(虽然做得不如三星和惠普好),爱普生 有 Epson Download Navigator 和统一的 Linux 包。

2017 年,惠普收购了三星的打印机业务。此后三星打印机的 ULD 维护转到了惠普手上,但那个包依然叫"Samsung Unified Linux Driver",因为它服务的是三星品牌的老型号。新出的惠普品牌打印机则由 HPLIP 覆盖。

ULD 之所以重要,是因为它解决了 Linux 打印生态的一个根本矛盾:私有格式需要闭源过滤器才能工作,而开源社区没有能力也没有合法途径去逆向和维护所有厂商的私有格式。ULD 是厂商对 Linux 社区伸出的橄榄枝——“我的格式我不公开,但我给你一个能用的驱动包,你装上就行。” 虽然这对开源纯粹主义者来说不够理想(很多 ULD 过滤器是闭源的二进制 blob),但在实用层面上,它让数以百万计的低端打印机在 Linux 上变得可用了。


第七回:天下大势,分久必合——Driverless 时代

私有格式搞得天怒人怨——不光 Linux 用户不爽,手机用户(iOS、Android)也不爽。你让 iPhone 怎么安装一个三星的 ULD?你让 Android 平板怎么装一个佳能的 CAPT 驱动?

于是行业终于开始寻求统一了。

2010 年前后,苹果推出了 AirPrint。苹果对打印机厂商说:“你要想让 iPhone 和 iPad 用户能直接打印,你的打印机就必须能直接接收 PDF 或者标准光栅格式(Apple Raster, URF),我不管你内部用什么语言,你自己在打印机固件里做好转换。” 苹果的市场影响力太大了,厂商纷纷跟进。

差不多同一时期,PWG(Printer Working Group,一个行业标准组织)制定了 IPP Everywhere 标准和 PWG Raster 格式。IPP Everywhere 的理念和 AirPrint 一样:打印机必须能直接接收通用格式(PDF 或 PWG Raster),由打印机自己负责渲染——也就是说,打印机里又得有一个"脑子"了。

2013 年,一群安卓设备厂商和打印机厂商成立了 Mopria Alliance,推出了基于 IPP 的 Mopria 打印标准,目标是安卓设备的无驱动打印。

这三股力量汇聚在一起,终于推动了"无驱动打印(Driverless Printing)"的普及。2017 年之后出厂的大部分打印机,至少在网络打印模式下都支持某种程度的无驱动打印。CUPS 2.x 也全面拥抱了这个趋势——你把打印机通过网络接入,CUPS 自动通过 IPP 发现它、查询它支持的格式、直接发送 PDF 或 PWG Raster,不需要安装任何驱动。

但,注意这个"但"字——这一切的前提是打印机支持 IPP Everywhere 或 AirPrint,而且通常是通过网络连接的。那些通过 USB 连接的旧型号激光打印机,固件里根本没有 IPP Everywhere 的实现,它们的 USB 接口只认 SPL 之类的私有数据流。对于这些"老古董",你该装 ULD 还是得装 ULD,无驱动打印帮不了你。


第八回:回到你的问题——所有困惑的终极答案

现在,把整个故事串起来,你的每个困惑都有了答案。

“为什么纯文本可以正确打印,复杂排版不行?”

因为纯文本太简单了。纯文本没有精确的坐标、没有混合字体、没有表格线。CUPS 用 texttopdf 把它转成一个最简单的 PDF(等宽字体、固定行距),然后通用光栅化过滤器把这个简单 PDF 渲染成像素。由于内容简单,哪怕可打印区域算得不太精确、分辨率不太匹配,肉眼也看不出问题。但当你有精确的排版(毫米级的边距控制、多列布局、条码、表格),通用驱动的 PPD 里那些"猜"出来的参数就不够用了——可打印区域偏了一两毫米,表格线就对不齐;纸张大小不精确,整个页面就缩放变形。

“为什么只有专用驱动才能正确打印格式?”

因为 ULD 等专用驱动的 PPD 文件是厂商根据打印机的硬件规格精确编写的——每个纸张大小对应的可打印区域精确到小数点后两位,支持的分辨率是经过硬件验证的真实值,颜色模式和位深与打印引擎完全匹配。而且对于使用私有格式的打印机,ULD 里的专用过滤器(如三星的 rastertosamsungspl、惠普 HPLIP 里的闭源插件)是唯一能生成打印机理解的数据格式的程序。没有它,你把 PostScript 还是 PCL 发过去,打印机根本不认识。

“ULD 和一般的打印有什么区别?”

ULD(以及 HPLIP 等类似方案)是厂商为旗下使用私有格式的打印机提供的 CUPS 过滤器和 PPD 包。它把这个品牌旗下几十上百个型号的驱动统一打包,一次安装全部搞定。“一般的打印”——如果你指的是通用驱动——走的是 PostScript 或 PCL 通用过滤器链,适用于支持标准 PDL 的打印机。低端 GDI 打印机不支持标准 PDL(或只有残缺的支持),所以通用驱动打不好,必须安装对应品牌的 ULD 才能正常工作。

“为什么 Docker 里不 work?”

因为你在宿主机上已经装好了 ULD(PPD + 过滤器 + 共享库),CUPS 能调用完整的过滤器链。把应用放进 Docker 容器后,如果容器内运行了自己的 CUPS,那个 CUPS 缺少 ULD 的过滤器和 PPD,过滤器链断了。如果容器通过网络连接宿主机的 CUPS,那 IPP 连接可能没配好(socket 没挂载、端口没暴露、访问控制没放开)。这不是什么玄学,而是——从活字印刷到 SPL,一千年来打印的本质没变:你得把信息正确地"翻译"成纸上的墨迹。 翻译链条上断了任何一环,打印就不 work。


这就是打印江湖的千年演义——从毕昇的泥活字,到 Adobe 的 PostScript,到三星的 SPL,到惠普的 HPLIP,到今天的无驱动打印。格式多如牛毛,不是因为工程师们吃饱了撑的,而是因为在"成本、性能、通用性、精确性"这四个维度上,不同时代、不同厂商做了不同的取舍。每一种格式的诞生,都是某个时代、某种商业环境、某种技术约束下的最优解。ULD 这类统一驱动包,则是厂商在私有格式的现实和 Linux 多发行版生态之间找到的一个务实折中——不完美,但管用。理解了这些,你再去看 CUPS 的过滤器链、PPD 文件、ULD 驱动包,就不再是一堆莫名其妙的配置文件了——它们是这条千年翻译链上的各个环节,每一个都有它存在的理由。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值