打印慢的原因


java的RasterPrinterJob会执行很多次printPage方法

他应该是按块填充的, 如果页面元素非常复杂, 那么printPage方法可能会执行十几次.

而如果你用了如下代码中流式打印的方式, 每页pdf单独实现Printable接口, 重写print方法.

     private static class FinePrintableDemo implements Printable {

         public FinePrintableDemo(PDDocument document, int index) {
this.index = index;
this.printable = new PDFPrintable(document);
} private int index;
private PDFPrintable printable; @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
int res = printable.print(graphics, pageFormat, index);
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (index + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 "); return res;
}
}

会发现print方法同样被执行了十几次, 造成一个带背景的pdf打印耗时十几秒.

慢在哪


慢在每次都重复解析同一页pdf内容. 打了断点后会发现每页都在PDFStreamEngine.processStream

     public void renderPageToGraphics(int pageIndex, Graphics2D graphics, float scale) throws IOException {
PDPage page = this.document.getPage(pageIndex);
this.transform(graphics, page, scale);
PDRectangle cropBox = page.getCropBox();
graphics.clearRect(0, 0, (int)cropBox.getWidth(), (int)cropBox.getHeight());
PageDrawerParameters parameters = new PageDrawerParameters(this, page);
PageDrawer drawer = this.createPageDrawer(parameters);
drawer.drawPage(graphics, cropBox);
}

这个方法每次都会消耗1s左右.

怎么解决


最好的方式自然是改pdfbox源码, 不用每次都重新生成解析pdf文件. 不过那样稍微有点麻烦.

还有个更简单的方式, 既然pdf会被反复解析, 那么我们在print之前把pdf转成图片, 然后直接打印图片即可.

即使RasterPrinterJob.printPage执行十几次, 也不过在绘制Image, 时间会非常短.

因此我们将代码稍微改造下, 在printable.print方法中直接打印图片.

   private static class FinePrintableDemo implements Printable {

         private BufferedImage image;

         public FinePrintableDemo(PDDocument document, int index) {
// 获取pdf文件, 将其中指定的页面转成图片.
PDFRenderer renderer = new PDFRenderer(document);
try {
this.image = renderer.renderImage(index, 1, ImageType.RGB);
} catch (IOException e) {
e.printStackTrace();
} } @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
Graphics2D g2d = (Graphics2D) graphics.create();
Paint paint = g2d.getPaint(); int width = this.image.getWidth();
int height = this.image.getHeight(); Shape shape = new Rectangle2D.Double(0, 0, width, height);
g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
g2d.fill(shape);
g2d.setPaint(paint);
g2d.dispose();
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
return Printable.PAGE_EXISTS;
} private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
Rectangle2D rec2D = shape.getBounds2D();
if ((int) rec2D.getWidth() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
}
if ((int) rec2D.getHeight() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
}
BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = buffered.createGraphics();
GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB); g2.dispose(); return new TexturePaint(buffered, rec2D);
}
}

这一次print方法同样被执行了十几次, 但是每次也就十几毫秒, 文件很快就被打印出来了.

完整代码如下

 package com.fr.base;

 import com.fr.stable.Constants;
import com.fr.stable.StableUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer; import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.TexturePaint;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; public class doStreamImagePrint { public static void main(String[] args) throws IOException, PrinterException {
PrinterJob job = PrinterJob.getPrinterJob(); int width = 595;
int height = 842;
int marginLeft = 0;
int marginRight = 0;
int marginTop = 0;
int marginBottom = 0; Paper paper = new Paper();
paper.setSize(width, height);
// 设置边距
paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
// 自定义页面设置
PageFormat pageFormat = new PageFormat();
// 设置页面横纵向
pageFormat.setOrientation(PageFormat.PORTRAIT);
pageFormat.setPaper(paper); // 构建一个有size的空book, book里都是引用. 实际打印哪一页就从远程获取哪一页
Book printBook = new Book();
// 真正打印的时候, 每页的printable都new pdfprintable.print();
printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat);
printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat); job.setPageable(printBook);
job.print();
} private static FinePrintableDemo convertPDFToPrint(String path, int index) throws IOException {
InputStream in = new FileInputStream(path);
PDDocument document = PDDocument.load(in);
return new FinePrintableDemo(document, index);
} private static class FinePrintableDemo implements Printable { private BufferedImage image; public FinePrintableDemo(PDDocument document, int index) {
// 获取pdf文件, 将其中指定的页面转成图片.
PDFRenderer renderer = new PDFRenderer(document);
try {
this.image = renderer.renderImage(index, 1, ImageType.RGB);
} catch (IOException e) {
e.printStackTrace();
} } @Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
long start1 = System.currentTimeMillis();
Graphics2D g2d = (Graphics2D) graphics.create();
Paint paint = g2d.getPaint(); int width = this.image.getWidth();
int height = this.image.getHeight(); Shape shape = new Rectangle2D.Double(0, 0, width, height);
g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
g2d.fill(shape);
g2d.setPaint(paint);
g2d.dispose();
long end1 = System.currentTimeMillis();
System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
return Printable.PAGE_EXISTS;
} private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
Rectangle2D rec2D = shape.getBounds2D();
if ((int) rec2D.getWidth() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
}
if ((int) rec2D.getHeight() <= 0) {
rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
}
BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = buffered.createGraphics();
GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB); g2.dispose(); return new TexturePaint(buffered, rec2D);
}
} }

PDFBox 打印带背景的文件速度慢的更多相关文章

  1. Lodop如何设置预览后导出带背景的图,打印不带背景图

    Lodop中的ADD_PRINT_SETUP_BKIMG,可以加载上背景图,该背景图在预览的时候可以显示也可以不显示,打印可以打印出来也可以不打印出来.一般套打,都是不打印背景图的,比如一些快递的快递 ...

  2. 导出不带.svn的文件夹或者是不含.class的文件

    转载自:http://blog.csdn.net/z278718149/article/details/21537395 如何导出不带.svn的文件夹或者是不含.class的文件 在工作环境中,有的时 ...

  3. 如何导出不带.svn的文件夹

    在工作环境中,有的时候需要将本地SVN服务器中的文件导出来,提交到另一个SVN服务器中去(比如做现场开发时,由于外网速度慢,项目组内部往往使用一个SVN服务器,但又同时又需要公司统一管理,定期提交到公 ...

  4. Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录)

    Java 打印金字塔 or 打印带数字的金字塔 (Java 学习中的小记录) 作者:王可利(Star·星星) 效果图: 代码如下: class Star8 { public static void m ...

  5. git bash中带空格的文件夹以及文件的处理

    空格用'\ '表示,输入的时候,是不需要单引号的 total 338drwxr-xr-x 9 Administ Administ 4096 Aug 24 23:53 HDTHelperdrwxr-xr ...

  6. Python_服务器与多客户端通信、UDP协议、pycharm打印带颜色输出、时间同步的机制

    1.服务器与多客户端通信 import socket # 创建tcp socket的套接字 sk = socket.socket() # bind sk.bind(('127.0.0.1',8080) ...

  7. Lodop打印控件不打印css背景图怎么办

    background:url()这是css背景图,http协议会按异步方式下载背景图,所以很容易等不到下载完毕就开始打印了,故lodop不打印css背景图.Lodop不打印css背景图,但是有其他方法 ...

  8. linux下怎么删除名称带空格的文件

    linux下怎么删除名称带空格的文件-rm 'mysql bin.000005' 用引号把文件名括起来 某些情况下会出现名称带空格的文件, 如果想要删除的话,直接用rm mysql bin.00000 ...

  9. phpqrcode 分别生成普通、带logo、带背景带logo二维码

    前提:下载好 phpqrcode 类库 1.生成普通二维码 //引入类库 include('phpqrcode/phpqrcode.php'); //二维码里面的链接地址 $url="htt ...

随机推荐

  1. Leetcode题解(十五)

    42.Trapping Rain Water 题目 这道题目参考http://www.cnblogs.com/felixfang/p/3713197.html 观察下就可以发现被水填满后的形状是先升后 ...

  2. spring框架应用系列三:切面编程(带参数)

    本文系作者原创,转载请注明出处:http://www.cnblogs.com/further-further-further/p/7786715.html 解决问题 1.分离业务监控与业务处理.简单点 ...

  3. Cocoapods使用过程中遇到的问题

    前言:记录一些在CocoaPods使用过程中遇到的问题,本地环境:Xcode9.0 发现有的时候在执行pod init的时候不能正常地创建出来pod File文件,显示的错误如下: ――― MARKD ...

  4. Mybatis整理_01

    Mybatis专题 Mybaits介绍 Mybatis是一个持久化框架,它有不同语言的版本,比如.NET和Java都有Mybatis对应的类库:它有大多数ORM框架都具有的功能,比如自定义的SQL语句 ...

  5. RE: Javascript分页处理

    背景: 调用PHP后端给的接口,以实现分页的功能.由于我是没造轮子的能力,所以翻了不少技术博客,经过整合才算完成整个分页功能.从一番查阅中,不难看出大概分为两种不同的分页: 一种是纯前端的,就是在一次 ...

  6. Python把给定的列表转化成二叉树

    在LeetCode上做题时,有很多二叉树相关题目的测试数据是用列表给出的,提交的时候有时会出现一些数据通不过,这就需要在本地调试,因此需要使用列表来构建二叉树,方便自己调试.LeetCode上二叉树结 ...

  7. Git(1)----Eclipse安装Git插件

    一.从官网选择系统版本下载Git并安装 地址:https://git-scm.com/downloads/ 二.打开Eclipse 1. 第一种安装方法: help-->Install New ...

  8. Oracle与Sql server的区别

    一直搞不明白Oracle数据库和sql server的区别,今天我特意查资料把他们的区别整理出来 Oracle数据库:Oracle Database,又名Oracle RDBMS,或简称Oracle. ...

  9. openpose模型在AI challenge人体骨骼关键点检测的表现

    因为之前正好看了CMU在CVPR2017上的论文<Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields>, ...

  10. 我两年的web开发生涯

    我两年的web开发生涯 与以前的文章分享给大家自己的知识和观点不同,这篇文章更多的是写给自己的总结. 现在是 2017年10月18. 从 2015年9月 开始接触前端开发,至今两年零一个月. 从 20 ...