打印慢的原因


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. java使用for循环做猜数字游戏

    package org.llh.test;import java.util.Random;import java.util.Scanner;/** * 猜数字游戏 *  * @author llh * ...

  2. HDU1166 敌兵布阵(线段树)

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...

  3. A - 棋盘问题 POJ - 1321

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. ...

  4. Linux系统安装_Centos6.9

    第1章 虚拟机安装  1.1 镜像下载 1.1.1 新版本下载 http://mirrors.aliyun.com  #阿里云官方镜像站点 1.1.2 旧版本下载 http://vault.cento ...

  5. 0_Simple__cdpSimplePrint + 0_Simple__cdpSimpleQuicksort

    CUDA动态并行的简单实践,以及利用CUDA动态并行实现快排算法(有单线程的递归调用) ▶ 源代码:动态并行递归调用线程块 #include <iostream> #include < ...

  6. jQuery选择器(添加节点及删除节点及克隆及替换及包装)第九节

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. windows系统扩展C盘的工具推荐(解决了C盘和压缩卷不相邻无法扩展C盘问题)

    1.下载分区工具 “分区助手3.0中文版” 下载地址:http://www.33lc.com/soft/14880.html 2.下载下来是一个压缩包,解压后运行安装程序. 3.安装完成后按以下步骤执 ...

  8. Java工具类之——BigDecimal运算封装(包含金额的计算方式)

    日常对于金额计算,应该都是用的BigDecimal,  可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这个,简单粗暴好用,话不多说,代码奉上(该工具类需要引入g ...

  9. C#移位运算(左移和右移)

    C#是用<<(左移) 和 >>(右移) 运算符是用来执行移位运算. 左移 (<<) 将第一个操作数向左移动第二个操作数指定的位数,空出的位置补0.  左移相当于乘. ...

  10. web前端-----jQuery

    web前端之jQuery篇 一 jQuery是什么? [1]   jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. [2]   j ...