.Net下的PDF打印
简单研究了一下.Net下的PDF打印,一路发现了很多小坑。
第三方组件
这里使用的解析PDF的组件是mupdf,特点和C#调用在 这里 有介绍。
实现的功能
支持页面大小、边距、打印机选择、打印机dpi、打印范围、单双面、奇偶页、缩放、对齐、填充、打印份数、自动旋转等。
关于pt、px、dpi、inch的解释
pt
点(Point)。pt是一种固定长度的度量单位,是能够使用测量设备测得的长度。绝对单位作用有限,因为它们不能够缩放。1点 = 0.376毫米 = 1.07英美点 = 0.0148英尺 = 0.1776英寸。
1英寸 = 72点。
px
像素(Pixel),屏幕最小的显示单元。常见分辨率,如高清的1920*1080,即表示横纵分别有1920和1080个像素点。dpi
每英寸(Inch)长度内的像素点数。dpi越高,即每英寸内的像素点越多,描述细节的能力也就越高,即清晰度越高。Inch
即英寸。1英寸 = 2.54厘米。
通过以上可以得到下面的公式。注意这个计算在后续频繁用到。
dx/dpi = inch = pt /72
即,dx = pt * dpi / 72
打印配置类
.Net的System.Drawing.Printing
下面支持的打印功能类基本满足了开发需要。其中,
PageSettings
类初始化后即为当前的默认打印机的页面属性配置。值得注意的是,PageSettings.Bounds
的单位是百分之一英尺,这一点十分重要!PrinterSettings
类初始化后即为当前默认打印机的属性配置。同样,PrinterSettings.PaperSizes
是PaperSize
的集合,即打印机支持的纸张类型。PaperSize
的单位,同样是百分之一英尺。
PDF的页面的尺寸
在mupdf中,pdf的页面尺寸是由函数pdf_bound_page
计算得到的,其单位是pt,注意了,这个单位和上面打印配置的纸张尺寸单位是不一致的。
打印实现方式
mupdf本身没有支持打印,这里使用mupdf将pdf页面转换成图片(System.Drawing.Bitmap
),使用.Net的打印组件将图片渲染到打印机。因此,打印过程需要自己控制各项打印配置。其中,纸张大小、打印颜色、单双面打印等可以在打印配置类中配置,而自动旋转、缩放、打印范围、奇偶页打印等需要自行控制。如果没有考虑上述单位不一致的问题,会导致使用PrintDocument.DrawImage
时,渲染的图片实际偏小。考虑到:
设打印机配置的纸张尺寸数值为SzP0,以英尺为单位的纸张尺寸为SzP1。以pt为单位的纸张尺寸为SzP2,则
SzP0 / 100 = SzP1 = SzP2 / 72,即
SzP2 = SzP0 / 100 * 72
因此,当pdf使用单位为pt时,纸张使用百分之一英尺的数值会让纸张尺寸实际偏大。
关于打印dpi
不同打印机支持不同的打印dpi,有的打印机甚至可以配置打印dpi。打印dpi影响什么呢?例如,一个a0 Inch(pt单位的数值为a1)的纸张(仅用一个维度说明),其dpi为dpi0,图片的尺寸为a2 px,那么可以做如下计算:
a2 / dpi0 = a0 = a1 / 72
其中,a0和a1大小对应且固定不变,则dpi0越大,a2也将会越大。结论是:
打印出结果的物理尺寸不变的情况下,dpi越高,待打印图片的像素要求也将越高。因此,为了保证打印结果足够的清晰度,需要调高打印机的dpi(如果支持)。而为了保证得到预期的结果尺寸,则同时需要提供更高分辨率的图片。
关于预览
demo的界面使用wpf实现,打印预览是通过Control.OnRender
中的DrawingContext
绘制图片来实现的。为了提高性能,预览的图片可以适当减小渲染精度(尺寸),因为本身预览图是缩放了的。
另外,为了保持不同纸张的预览图尺寸相对固定,使用固定尺寸的ViewBox来控制预览控件的大小。
遇到的异常
值“0”不是枚举“PaperSourceKind”的有效值
英文报错为:The value '0' is not a valid value for the enum 'PaperSourceKind。
这个问题是因为,某些打印驱动,对枚举PaperSourceKind给的值是0,属于非法的枚举值,当调用ToString方法时,就会抛出异常。根据了解到会发生这个问题的打印驱动包括:Solid Pdf Creator
和PCL6 Driver for Universal Print
(问题参考这里)。下面给出正常和异常的值示例:
// Microsoft Pdf Printer
{[PaperSource unknown Kind=FormSource]}
Kind: FormSource
RawKind: 15
SourceName: "unknown"
// Solid Pdf Creator
{System.Drawing.Printing.PaperSource}
Kind: 0
RawKind: 0
SourceName: "unknown"
感谢
感谢wmjordan提供的mupdf的.Net调用和图片转换教程。
.Net下的PDF打印的更多相关文章
- 开源免费且稳定实用的.NET PDF打印组件itextSharp(.NET组件介绍之八)
在这个.NET组件的介绍系列中,受到了很多园友的支持,一些园友(如:数据之巅. [秦时明月]等等这些大神 )也给我提出了对应的建议,我正在努力去改正,有不足之处还望大家多多包涵.在传播一些简单的知识的 ...
- 基于iTextSharp的PDF操作(PDF打印,PDF下载)
基于iTextSharp的PDF操作(PDF打印,PDF下载) 准备 1. iTextSharp的简介 iTextSharp是一个移植于java平台的iText项目,被封装成c#的组件来用于C#生成P ...
- 驰骋CCFlow开源工作流程引擎如何设置PDF打印
前言 经常有驰骋CCFlow爱好者朋友提问关于打印相关问题.在这篇博文中大家介绍一下工作流引擎CCFlow的HTML打印和PDF打印,针对Java版本和.NET版本有不同的操作步骤,包括开关设置.水印 ...
- [转].NET下读取PDF文本
本文转自:http://blog.csdn.net/wangqiuyun/article/details/8548779 在.NET下读取PDF文本用到的类库主要有两个:PDFBox和iTextSha ...
- 7款Linux下阅读PDF的阅读器。
5款Linux下阅读PDF的阅读器.1. Mupdf:link 2. Adobe Reader:link 3. Foxit Reader:link 4.Evince:link 5. Okular:li ...
- Objective-C与Swift下的自定义打印函数(Debug和Release)
1.Objective-C 在使用Objective-C进行开发的过程中,为了Debug会不断的设置打印函数.如下图是我们经常用的,用来测试监听方法的实现与否: NSLog(@"%s&quo ...
- C#将制定文件夹下的PDF文件合并成一个并输出至指定路径
/// <summary> /// 将源路径下的PDF合并至目标路径下 /// </summary> /// <param name="SourcePath&q ...
- linux下使用小票打印
linux下使用小票打印 打印机: Xprinter XP-58IIH指令支持: ESC/POS接口: USB, 蓝牙 Linux系统: Centos7 蓝牙配对很快, 配对好后就是连接状态. 但很快 ...
- 剑指offer60:把二叉树打印成多行。上到下按层打印二叉树。
1 题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 2 思路和方法 vector变量存储每一层的元素vector<vector<int> > ans ...
随机推荐
- 同一个网段内所有服务器virtual_router_id设置相同的后果
/var/log/messages中一直报的错 one or more VIP associated with VRID mismatch actual MASTER advert bogus VRR ...
- 小程序map学习:使用map获取当前位置并显示出来
在小程序开发的过程中,我碰到过一个做map的需求,在我开发的时候我碰到了一些问题,这里总结出来,给大家一些解决方法. 简易小程序dome下载 代码片段分享: js部分: var amapFile = ...
- 转 Fiddler3 使用技巧
Fiddler3 使用技巧 文章转自:https://www.cnblogs.com/zhengna/category/1466001.html 1.Fiddler抓不到包怎么解决 (1)先确定是H ...
- Correct the classpath of your application so that it contains a single, compatible version of org.thymeleaf.spring5.SpringTemplateEngine
Error starting ApplicationContext. To display the conditions report re-run your application with 'de ...
- int ping = 11; 限流 客户端验证与服务端是连接的
int ping = 11; ZooKeeper Programmer's Guide https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgram ...
- 我感兴趣的 .NET 开源项目
Gui.cs - 用于.NET 的控制台终端 UI 工具包 https://github.com/migueldeicaza/gui.cs Newtonsoft.Json - 高性能的 JSON 解析 ...
- 内联扩展 inline expansion An Inline Function is As Fast As a Macro 与宏的比较
让编译器直接将完整的函数体插入到每一个调用该函数的地方,从而提高函数调用的运行速度. 优秀的JIT编译器会通过侦测运行信息,仅将需要频繁运行的瓶颈部分进行编译,从而大大削减编译所需的时间. 而且,利用 ...
- loj10003加工生产调度
题目描述 某工厂收到了 n个产品的订单,这 个产品分别在 A.B 两个车间加工,并且必须先在 A 车间加工后才可以到 B 车间加工. 某个产品 i 在 A,B 两车间加工的时间分别为 A_i,B_i ...
- Spring听课笔记(专题二下)
第4章 Spring Bean基于注解的装配 4.1 Bean的定义及作用域的注解实现 1. Bean定义的注解 -- @Component是一个通用注解,可用于任何bean -- @Reposito ...
- Spark使用Java、Scala 读取mysql、json、csv数据以及写入操作
Spark使用Java读取mysql数据和保存数据到mysql 一.pom.xml 二.spark代码 2.1 Java方式 2.2 Scala方式 三.写入数据到mysql中 四.DataFrame ...