打印慢的原因


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. ABAP开源项目清单

    因为曾经的“SAP Code Exchange”平台已经于2013年倒闭,现在无论在SCN还是网络上都比较难找到一个地方来关注全部的优秀ABAP开源项目. 本文将这些项目的地址和他们的描述列出,以供参 ...

  2. CSS3新增伪类汇总

    :root 选择文档的根元素,等同于 html 元素 :empty 选择没有子元素的元素 :target 选取当前活动的目标元素 :not(selector) 选择除 selector 元素意外的元素 ...

  3. HDU Today

    HDU Today Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  4. Circle

    Circle   Memory Limit: 32768KB   64bit IO Format: %lld & %llu Status Description Your task is so ...

  5. CIFAR-10 dataset 的下载与使用

    基本信息 CIFAR-10 是一个包含60000张图片的数据集.其中每张照片为32*32的彩色照片,每个像素点包括RGB三个数值,数值范围 0 ~ 255. 所有照片分属10个不同的类别,分别是 'a ...

  6. js input输入事件兼容性问题

    if(navigator.userAgent.indexOf('Android') > -1){ $("#sign").on("input", funct ...

  7. rewirte 规则

    Nginx Rewrite Rewirte 规则也称为规则重写,主要功能是实现浏览器访问 HTTP URL 的跳转,其正则 表达式是基于 Perl 语言.通常而言,几乎所有的 WEB 服务器均可以支持 ...

  8. 学习笔记-----php搭建用户管理系统

    后台:php,数据库:mysql,前端:html,css,js; 主要页面介绍: 1.php连接数据库后台,读取数据并将其以表格的形式显示,并且有添加,编辑,删除,分页等功能: 2.php用于添加用户 ...

  9. 由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别

    之前通过读书,了解到在Python中可以通过__new__方法来实现单例模式,代码一个示例如下,我就有了几个疑问,什么是单例模式?__new__方法是用来做什么的?用__new__方法实现的单例模式, ...

  10. 坦言spring中事务、重试、异步执行注解

    一.@Transaction 我们再编码过程中,大量使用到这个注解.一般情况下,@Transaction使用默认注解可以完成90%的功能,下面会针对一些特殊场景下,@Tansaction的使用注意 1 ...