C# PostScript文件生成 C#如何创建用于打印的.ps或.eps文件

5次阅读

postscript 和 eps 必须手写或调用外部库生成,c# 无原生支持;eps 需严格遵循 dsc 规范,含正确头、boundingbox 和字体设置;推荐 pdf→ghostscript 转 eps 路径。

C# PostScript文件生成 C#如何创建用于打印的.ps或.eps文件

PostScript 是纯文本格式,C# 本身不提供原生 API 生成 .ps 或 .eps

你没法用 System.DrawingprintDocument 直接输出标准 PostScript —— 它们在 windows 上走 GDI,最终由打印机驱动转译,你拿不到原始 PS 流。真正可控的方式只有手写或调用外部库生成符合规范的文本内容。

常见错误现象:PrintDocument 设置 PrinterSettings.PrinterName 为 “microsoft Print to PDF” 或 “Generic / Text Only” 后发现输出是乱码或空白,因为这些驱动根本不吐 PS,只是假装支持;更隐蔽的是某些网络打印机开启“PS emulation”后仍返回 PCL,导致你写的 %!PS-Adobe-3.0 头被忽略。

  • EPS 必须以 %!PS-Adobe-3.0 EPSF-3.0 开头,且含严格 BoundingBox 注释(如 %%BoundingBox: 0 0 595 842),缺一不可,否则多数 RIP 拒绝渲染
  • 所有坐标、字体名、操作符必须按 Adobe DSC 规范对齐,比如 show 前必须先 setfont,不能依赖默认状态
  • 中文/Unicode 字符需提前转成 Type1 字体子集或使用 stringwidth + rmoveto 手动定位,C# 里没现成函数帮你干这事

最简可行方案:用 StreamWriter 写合规的 EPS 文件头 + 基础绘图命令

绕过所有高级封装,直接控制输出流。适合生成条码、单色矢量标签、嵌入式打印模板等确定性场景。

关键点在于:EPS 不是“画完再导出”,而是“边构造边验证”。下面这段能被 Ghostscript 正确解析并转 PNG:

%!PS-Adobe-3.0 EPSF-3.0 %%BoundingBox: 0 0 200 100 %%HiResBoundingBox: 0 0 200 100 /Helvetica findfont 12 scalefont setfont 0 80 moveto (Hello World) show 0.5 setlinewidth 0 0 moveto 200 100 lineto stroke showpage
  • %%BoundingBox 必须真实反映内容边界,Ghostscript 的 -dEPSCrop 会裁剪它,但 Illustrator 等软件直接报错加载失败
  • 不要用 gsave/grestore 嵌套过深,某些老旧 RIP 有深度限制(常见 16 层)
  • 避免 currentpoint 类动态查询,它在 EPS 中语义模糊,改用绝对坐标 + translate

需要图形变换或字体嵌入?用 Ghostscript 的 ps2write 设备反向生成

与其手动拼 PS,不如让 C# 生成 PDF(用 iTextSharp 或 QuestPDF),再调 gswin64c.exe 转换。这是目前 Windows 下最稳的 EPS 产出路径。

命令行示例(注意参数顺序不能错):

gswin64c.exe -q -dNOPAUSE -dBATCH -dEPSCrop -sDEVICE=ps2write -sOutputFile=output.eps input.pdf
  • -dEPSCrop 必须启用,否则输出是带页边的 PS,不是 EPS
  • ps2write 设备比 epswrite 更可靠,后者在 GS 10+ 中已被标记为 deprecated
  • 输入 PDF 若含透明度或 CMYK 图片,转换后可能失真 —— EPS 本身不支持透明,GS 会强制 flatten

别碰 System.Drawing.ToImage() → 转 PS 这条路

有人试图把 Bitmap 保存为 EMF,再用第三方工具转 PS,结果发现文字锯齿、线宽不准、CMYK 色彩偏移。根本原因是 EMF 是设备无关但非 PostScript 的中间格式,转译时丢失了所有矢量语义。

典型翻车点:

  • Graphics.DrawString() 使用 StringFormat.GenericTypographic 后,生成的 EMF 在 GS 中显示缺字 —— 因为字体未嵌入,且 EMF 记录的是 GDI 调用而非 glyph path
  • 哪怕只画一条 Pen 线,DrawLine() 在 EMF 中记录为像素坐标,转 PS 后变成位图描边,放大即糊
  • 想用 Metafile.PlayRecord 提取 EMF 指令再映射到 PS?Adobe 技术白皮书明确说 EMF 不保证可逆映射,实测成功率低于 60%

真正要保证打印精度,就得从源头控制 PostScript 指令流 —— 这意味着放弃“所见即所得”的 ui 预览,接受文本编辑器里调试 movetolineto 的事实。

text=ZqhQzanResources