如何向现代打印机发送数据?PDF、PostScript、HPGL等。

12

我想了解一下在应用程序中与打印机进行程序化通信以打印内容的选项。换句话说,当用户告诉我的应用程序他们想要打印某些东西时会发生什么。我了解它在“旧日子”里是如何工作的,并正试图理解更加复杂的现代世界。

在旧日子里,有两种主要类型的打印机:理解HPGL和Postscript打印机的HP打印机。因此,您可以用这两种语言之一发送打印输出,打印机将把您的代码转换为页面上的点。您还可以嵌入位图作为二进制数据。例如,在HPGL(或PCL)中,您可以给出一个命令,基本上是“请打印这个位图,并附上光栅数据”,后跟一个巨大的二进制数据块。显然,如果这样做,发送到打印机的数据量将更多,可能会使打印机受阻。Postscript也具有相同的功能。如果打印文本,您可以告诉打印机使用TimesNewRoman字体(或其他),打印文本“xyz”,打印机将为您计算所有点(这意味着打印机必须知道字体,或者您必须提前将字体下载到打印机中)。

现在,据我所知,PDF格式类似于Postscript,但它不像Postscript那样是一种语言,只能包含“对象”。因此,例如,在Postscript中,您可以制作一个循环并说“打印这个圆形50000次”,将其确切位置移动。在PDF中,我理解的是您不能这样做,您必须将每个圆都指定为单独的“对象”。

那么,现代打印机是如何工作的呢?我还能向打印机发送HPGL / PCL吗?现在所有打印机都标准化为Postscript吗?如果是这样,那么我的最佳选择是生成Postscript,然后将其原始发送到打印机吗?如果我发送Postscript,我是否需要告诉打印机它是Postscript呢?

在Windows中,我知道“标准”的打印方式是查询设备功能并请求设备上下文,然后您可以使用Windows调用在该上下文中绘制线条、形状和文本。但是,显然这与Postscript(或HPGL/PCL)相比极为原始。是否有一种方法可以直接与打印机驱动程序通信,或告诉Windows:“这是我的Postscript代码,请将其传递给打印机进行打印”?


1
你在问题中标记了[windows]。你指的是哪个版本的Windows?Server 2000?XP?2003?Vista?Server 2012?Windows 8?8.1?10?RT?Mobile?CE?Phone? - Kurt Pfeifle
3
你已经得到了非常精确的答案,我认为现在是时候放弃你的悬赏或者添加评论解释为什么你认为这些答案实际上并没有回答你的问题。 - Marcus Müller
5个回答

17
“因此,例如,在Postscript中,您可以创建一个循环并说“打印此圆形50,000次”,同时将其确切位置移动。 在PDF中,我的理解是您无法这样做,必须将每个圆形单独指定为一个“对象”。”
实际上,事实更接近您描述的两个极端之间的中间地带。
1. 确实如此:与PostScript不同,PDF不是编程语言(更不用说图灵完备),不能定义“循环”。 2. 但是,您也不必分别指定每个圆(或嵌入式图像或其他图形对象)。 您可以很好地定义如何绘制一个圆(或图像或任何内容),然后在页面或PDF文档的其他位置重复使用该定义。 这称为“引用对象”。 当您重复使用对象时,可以通过更改某些当前的“环境”定义(例如包括CTM图形状态,即当前变换矩阵)以不同方式设置其不同的属性(颜色,缩放,旋转)。
关于您所提出的其他观点:
- 不,从来没有只有两种类型的打印机,HPGL和PostScript。 - 即使在过去,也有十几种不同的“打印机语言”。 PCL比HPGL更受欢迎。 还有不要忘记所有专有的打印机语言发明。 你听说过AFP,高级功能打印吗? 这种语言打印 - 并且仍在打印! - 比PostScript印刷纸张更多。 它不再是专有的,但它是IBM为主机打印大量可变数据而发明的,主要用于计费目的... 你听说过ESC / P吗? KPDL? XPS?
  • 是的,你仍然可以向打印机发送HPGL指令——但并非所有打印机都支持。打印机必须至少支持你能够生成和发送的其中一种语言。

  • 现在有些打印机型号可以直接处理PDF格式,但它们仍不是主流类型。其中一些“作弊”,仍然将PostScript引擎作为其主要内置解释器:这些打印机会将PDF文件默默地转换为PostScript格式。其他一些打印机则可以无需回退到PostScript格式即可处理PDF文件。


  • “在Windows中,我知道打印的‘标准’方式是查询设备功能并请求设备上下文,然后您可以使用Windows调用在该上下文中绘制线条、形状和文本。”

    不要假定术语“设备上下文”意味着Windows直接与打印机硬件通信以查询功能和请求设备上下文。有时是这样,有时不是。它总是依赖于称为“打印机驱动程序”的某些软件(还控制应将打印数据转换为哪种打印机语言)。打印机驱动程序可能能够查询设备并询问“你有双面装置吗?你有订书机吗?”然后为作业自己生成所需的设备上下文。

    只有一种非常现代的方法,IPP Everywhere,由打印机工作组开发,才能消除大部分旧版特定于型号的打印机驱动程序必须执行的操作,并开始主要依赖于在“无驱动程序”的情况下直接查询设备,以便最终确定要传递给物理设备的确切打印数据。

    但是,IPP Everywhere目前还不广泛流行,无论是对于供应商、管理员还是用户都是如此。但是一旦电脑被遗忘,95%的计算设备将是超级移动设备,它就会变得流行起来...


    14

    由于楼主不太喜欢我的(或任何其他人的)原始答案,因此他甚至授予了赏金。

    让我尝试添加可能缺失的内容到我的原始答案中。


    在早期,有两种主要类型的打印机:理解HPGL的惠普打印机和Postscript打印机。即使在早期,也有更多类型的打印机,或者说是页面描述语言...但对于大多数需要处理打印技术的人来说,PCL、HP/GL和PostScript可能是最重要的。因此,您可以使用这两种语言之一发送打印输出,打印机会将您的代码转换为页面上的点。但并非所有情况都适用,仅当打印机理解这两种语言时才可行(某些更昂贵的惠普型号可以实现)。

    一些打印机型号(即便在旧时代)只能理解HP/GL。有些则只能理解特定版本的PCL(PCL是一个完整的打印机语言家族,由大约十几个成员组成:其中一些较新的成员与旧成员几乎没有任何遗传相似之处,除了HP营销决定将它们称为PCL6PCL XL之外)。

    “那么现代打印机是如何工作的?我仍然可以向打印机发送HPGL/PCL吗?”

    是的,这仍然有效:

    • 如果你的“现代打印机”能够理解HP/GL,那么你可以向它发送HP/GL数据。
    • 如果它能够理解PCL,你可以发送PCL。
    • 如果它能够理解PostScript,你可以发送PostScript。
    • 如果它能够理解PDF,你可以发送PDF。
    • 如果它能够理解XPS(你听说过吗?!?),你可以发送XPS。
    • 但是,如果它只能理解PCL3(那么它就不是一台现代打印机:),你不能发送PCL6e...

    如果设备能够理解这些语言的任何组合,那么你可以自由地发送它所理解的内容。

    “现在,我了解PDF格式与Postscript类似,但它不像Postscript那样是一种语言,只能包含'对象'。例如,在Postscript中,你可以创建一个循环并说'打印这个圆形50,000次',同时移动它的确切位置。在PDF中,我的理解是你不能这样做。”

    你说得对,PDF(与PostScript不同)不是一种编程语言。这是一个设计决策,PDF不应理解循环或条件结构(而PostScript可以-PostScript甚至作为一种编程语言是图灵完备的,这意味着:任何可编程的东西都可以编写成一个PostScript程序)。
    因此,虽然您仍然可以将圆(甚至非常复杂的图形对象)定义为PDF对象:
    - 您不能通过非常短的编程语句来表达长循环,告诉渲染器在每次迭代期间显示该对象。 - 相反,您必须手动分别声明每个迭代(在那里您可以调用预先呈现的对象来显示)。
    但是当您陈述“PDF格式...类似于Postscript”时,您并不正确。它不是。 PDF源自与PostScript最初建立的相同的图形模型。但就这些而言。
    PDF运算符的关键字是不同的。典型PDF的结构与PostScript完全不同。
    最重要的是,PDF扩展了它从PostScript继承的图形模型(此外,它还添加了一些其他方面,以适合典型的电子文档)。它朝着几个方向发展:
    • 随着时间推移,它引入了更多的颜色空间。
    • 它支持更多字体类型。
    • 它为所有绘制的对象实现了“透明度”功能。
    • 它提出了“图层”的概念(PDF术语中的“可选内容组”,OCG)。
    • 它引入了交互式元素(按钮、链接、超链接、表单字段)。
    • 它支持更多不同的压缩方案。
    • 它可以利用更丰富的文档元数据集合。
    • 它引入了ICC颜色配置文件和全面的ICC颜色管理。
    • ...还有一些其他的特性。

    "现在所有的打印机都是基于Postscript标准吗?"

    不是的。

    如果说有什么的话,现代的打印机更喜欢PDF而不是PostScript(虽然它们仍然可能保留PostScript处理能力作为备选选项)。但最好向您的供应商咨询,或者研究他们的营销手册。

    "如果是这样,那么我的最佳选择是生成Postscript,然后将其原始发送到打印机,对吗?"

    那从来不是您最好的选择,即使在“旧日子”里也不是!

    毕竟,大多数情况下,打印比单页复杂的工作不仅涉及要求副本数量,还需要...

    • ...您还想选择页面大小,甚至为第一页(带有标头信件或蓝色封面纸)选择特定的托盘,为主体页面选择另一个托盘,为最后一张纸选择第三个托盘;
    • ...您想告诉设备将每个集合装订起来,或者在每张纸上打孔;
    • ...您想中心折叠和鞍钉一些工作,以获得成品小册子,
    • ...等等。

    这些作业功能不一定可以通过“原始PostScript”进行控制。要使用大多数PostScript打印机型号控制特定的打印作业选项,有两种方法:

    1. 将PostScript代码片段中的<< ...vendor-specific or generic PS-code...>> setpagedevice语句插入作业数据流中,可以在文档或单个页面级别上进行。

      要执行特定功能所需的特定setpagedevice是由相应的PostScript打印机驱动程序的PPD文件定义的。这个.ppd文件必须由相应的供应商与其打印机驱动程序一起提供。 PPD是由Adobe定义的文件格式规范。在某种程度上,它扩展了PostScript语言,并允许供应商在复杂的作业设置方面“发明”自己的功能。

    2. 在实际打印数据(以PostScript发送)之前,用包含几行(或多达几十行)以调用特定作业功能的PJL(简称打印机作业语言)头部对其进行前缀。

    PJL最初由惠普公司发明并用于PCL,但很快被其他供应商用于其他打印机语言。因此,现在大多数支持PostScript、PCLxx、HP/GL或PDF的打印机都可以使用PJL头行,因为它通常得到了大多数供应商的支持。在这种情况下,最后一条PJL行告诉打印机真正的作业数据是什么语言:PostScript、PCLxxx、PDF、HP/GL等等,通过类似于以下语句的方式:

        ESC%-12345X@PJL ENTER LANGUAGE = PostScript 
    

    如果我发送Postscript,那么我是否需要告诉打印机它是Postscript呢? 如果您在作业前添加PJL标头,则请参阅上面倒数第二段。
    对于纯PostScript打印机,您可能更愿意使用<<..>>setpagedevice语句。这样的打印机会自动理解PostScript...
    如果您列出您可以使用的打印机型号,这也将有所帮助。
    在Windows中,我知道打印的“标准”方式,即查询设备功能并请求设备上下文,然后可以使用Windows调用在该上下文上绘制线条、形状和文本。

    这实际上是在Windows上通过PostScript打印机(好吧,自从Windows 8以来基于XPSOXPS的新打印工作流程有些不同......)也是如此运作的。通常,“设备功能”已知并由相应的打印机驱动程序托管。当您使用Windows调用绘制线条、形状和文本时,驱动程序将把这些调用转换为PostScript并发送到打印机。

    这与Linux、Unix或Mac OS X的工作方式不同:

    在Linux(和Unix)中,每个应用程序都必须自己生成要发送到打印机的PostScript页面描述。没有“驱动程序”来帮助完成这项工作。如果最终目标打印机不支持PostScript,则CUPS将自动将其从收到的PostScript转换为供应商或型号特定的页面描述格式。(一些应用程序可能能够生成其中一种PCL语言。)
    在Mac OS X上,应用程序通常会生成PDF作为打印池格式(而CUPS会自动将此文件转换为不同的打印机语言,基于供应商的打印机驱动程序,该驱动程序通常包括所需的pdf-to-someting CUPS过滤器)。
    “然而,显然与Postscript(或HPGL / PCL)相比,这是极其原始的。”
    我不明白为什么您应该在这种情况下将其描述为“极其原始”。
    “有没有办法我可以直接与打印机驱动程序通信,或者告诉Windows:'这是我的Postscript代码,请将其传递给打印机进行打印'?”
    如我之前所说:在Windows上,如果一个应用程序想要打印到PostScript打印机,通常不会自己生成其PostScript代码[^1],也不会生成任何其他打印机特定格式的内容(除了最终设备是XPS打印机的情况)。通常,它会生成EMF作为溢出格式,并让打印子系统(和打印机驱动程序)处理可能需要的任何转换。
    或者你是在说:"我有这个预先制作的PostScript文件(在其他地方生成),我想要将其打印到PostScript打印机?" 如果是这样,那么只需从DOS命令行运行像lpr -S remoteserver -P printername "-o l" jobfile.ps这样的命令即可。
    话虽如此--是的,至少有两种非打印机驱动程序的方法可以用来查询您的打印设备:
    1. SNMP. 如果您的设备具有网络(以太网/ WiFi)接口并且理解简单网络管理协议,则可以通过此通道查询它,并获得对您所提出的任何SNMP类型问题的回答。用简单的语言来说(SNMP术语看起来有点不同):

      • 您当前的墨水水平是多少?
      • 您能处理的最大介质尺寸是多少?
      • 您有多少张纸盒?
      • 托盘1的填充水平是多少?
      • 您曾经打印过多少页?自上次启动以来打印了多少页?
      • 您可以处理哪些打印机语言?
      • 您支持哪种打印数据传输协议?HPJetDirect / AppSocket?LPR / LPD?IPP?
      • 您是否有可用的硬盘空间?
      • 您有多少RAM?
      • 目前还连接了哪些其他打印客户端?
      • ...等等。
    2. PJL查询。 通过向打印机发送几行简单的PJL语句(并评估响应),也可以检索上述某些信息。

    3. IPP查询。 如果设备可以使用IPP,则Internet Printing Protocol也支持查询设备功能。

    再说一遍:"有没有办法让我告诉Windows:'这是我的Postscript代码,请将其传递给打印机进行打印'?"

    您甚至可以完全绕过Windows,使用 netcat.exe 实用程序(有时也称为 nc.exe )向打印机发送作业文件:

    • Send a PostScript job to a network printer that waits on TCP port 9100 for incoming jobs:

      cat filename.ps | netcat.exe -h printer-ip-address-or-hostname -p 9100
      

      The same of course for PCL or any format jobs... IF the printer knows this format. Which exact TCP port you need to address depends on your specific model (look it up in the manual). How you create the PostScript, PCL or whatever file for the printer is up to you.


    [^1] ...除了一些像Acrobat这样的Adobe程序,它们确实可以生成自己的PostScript。


    将PS文件发送到打印机的另一种方法是调用API的ExtEscape函数,将打印机句柄、转义运算符POSTSCRIPT_DATA和PostScript数据作为参数传递。转义运算符QUERYESCSUPPORT也可用于查询驱动程序是否支持POSTSCRIPT_DATA转义。 - yms

    1
    我认为pdf基本上是编译后的postscript,如果不是相同的东西,那就只是一个被编译成二进制块,另一个是ascii。
    不是所有打印机都支持postscript,谢天谢地,它们往往会额外收费,而你可以在计算机上免费运行它,使用更少的资源并打印得更快。(或者在廉价的spooler上)
    PCL在非HP打印机以及HP上非常普遍。但是没有通用的答案。您仍然需要逐个打印机查看支持哪个,并/或已购买哪个作为其附加组件,然后从该列表中启用管理员所启用的内容。然后当然还有它所支持的语言版本。
    这就是CUPS的全部内容。一种抽象和隐藏这些细节的方法。

    -3
    在Windows环境中,常见的格式是WMF。Windows元文件。WMF是矢量和位图的组合。
    WMF格式是由微软制作的,用于与Windows GDI一起恢复图像。WMF文件包含重建图像所需的所有内容,因此它们可以转换为任何其他图形格式。
    打印机制造商通常会创建自己的打印机命令集。他们可以选择采用事实上的标准,并与专利/版权持有人达成协议。
    如果您制造Postscript打印机,则驱动程序将WMF转换为Postscript。
    通过Windows GDI API,Windows应用程序创建元数据(WMF),打印机制造商编写的Windows驱动程序将WMF转换为其自己的打印机命令。
    微软在一年前的昨天(2014年5月15日)将WMF规范发布到公共领域:Windows Metafile Format PDF 当您拥有“原始”(例如Postscript、HPGL)数据,该数据将被打印机正确解释时,必须绕过制造商的驱动程序。
    要绕过打印机的驱动程序,请使用通用/纯文本驱动程序。
    这样可以将驱动程序从图像中排除,然后您可以发送“原始数据”。
    然后,您必须发送驱动程序生成的所有代码,这些代码旨在使您的工作更轻松。

    如果你制造的是Postscript打印机,那么你的驱动程序将把WMF转换为Postscript并不正确。一个Windows应用程序通过Windows GDI API创建元数据(WMF),而由打印机制造商编写的Windows驱动程序将WMF转换为他们自己的打印机命令也不正确。实际上,驱动程序可以接收不同类型的输入,如XPS、Postscript、PCL或直接GDI函数调用,驱动程序会进行翻译。但是打印机驱动程序不需要直接处理WMF格式。 - yms

    -4

    如果您希望完全自动化打印流程,请安装FolderMill(http://www.foldermill.com/)。该程序会将打印文件自动转换为所需格式,选择一个空闲的打印机并生成打印任务。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接