Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >PDFBox 打印带背景的文件速度慢

PDFBox 打印带背景的文件速度慢

作者头像
用户1216491
发布于 2018-01-24 08:04:48
发布于 2018-01-24 08:04:48
2.3K00
代码可运行
举报
文章被收录于专栏:xdecodexdecode
运行总次数:0
代码可运行

打印慢的原因

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1     private static class FinePrintableDemo implements Printable {
 2 
 3         public FinePrintableDemo(PDDocument document, int index) {
 4             this.index = index;
 5             this.printable = new PDFPrintable(document);
 6         }
 7 
 8         private int index;
 9         private PDFPrintable printable;
10 
11         @Override
12         public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
13             long start1 = System.currentTimeMillis();
14             int res = printable.print(graphics, pageFormat, index);
15             long end1 = System.currentTimeMillis();
16             System.out.println("打印第 " + (index + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
17 
18             return res;
19         }
20     }

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

慢在哪

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1     public void renderPageToGraphics(int pageIndex, Graphics2D graphics, float scale) throws IOException {
2         PDPage page = this.document.getPage(pageIndex);
3         this.transform(graphics, page, scale);
4         PDRectangle cropBox = page.getCropBox();
5         graphics.clearRect(0, 0, (int)cropBox.getWidth(), (int)cropBox.getHeight());
6         PageDrawerParameters parameters = new PageDrawerParameters(this, page);
7         PageDrawer drawer = this.createPageDrawer(parameters);
8         drawer.drawPage(graphics, cropBox);
9     }

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

怎么解决

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 1   private static class FinePrintableDemo implements Printable {
 2 
 3         private BufferedImage image;
 4 
 5         public FinePrintableDemo(PDDocument document, int index) {
 6             // 获取pdf文件, 将其中指定的页面转成图片.
 7             PDFRenderer renderer = new PDFRenderer(document);
 8             try {
 9                 this.image = renderer.renderImage(index, 1, ImageType.RGB);
10             } catch (IOException e) {
11                 e.printStackTrace();
12             }
13 
14         }
15 
16         @Override
17         public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
18             long start1 = System.currentTimeMillis();
19             Graphics2D g2d = (Graphics2D) graphics.create();
20             Paint paint = g2d.getPaint();
21 
22             int width = this.image.getWidth();
23             int height = this.image.getHeight();
24 
25             Shape shape = new Rectangle2D.Double(0, 0, width, height);
26             g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
27             g2d.fill(shape);
28             g2d.setPaint(paint);
29             g2d.dispose();
30             long end1 = System.currentTimeMillis();
31             System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
32             return Printable.PAGE_EXISTS;
33         }
34 
35         private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
36             Rectangle2D rec2D = shape.getBounds2D();
37             if ((int) rec2D.getWidth() <= 0) {
38                 rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
39             }
40             if ((int) rec2D.getHeight() <= 0) {
41                 rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
42             }
43             BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
44             Graphics2D g2 = buffered.createGraphics();
45             GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
46                     Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB);
47 
48             g2.dispose();
49 
50             return new TexturePaint(buffered, rec2D);
51         }
52     }

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

完整代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  1 package com.fr.base;
  2 
  3 import com.fr.stable.Constants;
  4 import com.fr.stable.StableUtils;
  5 import org.apache.pdfbox.pdmodel.PDDocument;
  6 import org.apache.pdfbox.rendering.ImageType;
  7 import org.apache.pdfbox.rendering.PDFRenderer;
  8 
  9 import java.awt.Graphics;
 10 import java.awt.Graphics2D;
 11 import java.awt.Paint;
 12 import java.awt.Shape;
 13 import java.awt.TexturePaint;
 14 import java.awt.geom.Rectangle2D;
 15 import java.awt.image.BufferedImage;
 16 import java.awt.print.Book;
 17 import java.awt.print.PageFormat;
 18 import java.awt.print.Paper;
 19 import java.awt.print.Printable;
 20 import java.awt.print.PrinterException;
 21 import java.awt.print.PrinterJob;
 22 import java.io.FileInputStream;
 23 import java.io.IOException;
 24 import java.io.InputStream;
 25 
 26 public class doStreamImagePrint {
 27 
 28     public static void main(String[] args) throws IOException, PrinterException {
 29         PrinterJob job = PrinterJob.getPrinterJob();
 30 
 31         int width = 595;
 32         int height = 842;
 33         int marginLeft = 0;
 34         int marginRight = 0;
 35         int marginTop = 0;
 36         int marginBottom = 0;
 37 
 38         Paper paper = new Paper();
 39         paper.setSize(width, height);
 40         // 设置边距
 41         paper.setImageableArea(marginLeft, marginRight, width - (marginLeft + marginRight), height - (marginTop + marginBottom));
 42         // 自定义页面设置
 43         PageFormat pageFormat = new PageFormat();
 44         // 设置页面横纵向
 45         pageFormat.setOrientation(PageFormat.PORTRAIT);
 46         pageFormat.setPaper(paper);
 47 
 48         // 构建一个有size的空book, book里都是引用. 实际打印哪一页就从远程获取哪一页
 49         Book printBook = new Book();
 50         // 真正打印的时候, 每页的printable都new pdfprintable.print();
 51         printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat);
 52         printBook.append(convertPDFToPrint("D:\\bg.pdf", 0), pageFormat);
 53 
 54 
 55         job.setPageable(printBook);
 56         job.print();
 57     }
 58 
 59     private static FinePrintableDemo convertPDFToPrint(String path, int index) throws IOException {
 60         InputStream in = new FileInputStream(path);
 61         PDDocument document = PDDocument.load(in);
 62         return new FinePrintableDemo(document, index);
 63     }
 64 
 65     private static class FinePrintableDemo implements Printable {
 66 
 67         private BufferedImage image;
 68 
 69         public FinePrintableDemo(PDDocument document, int index) {
 70             // 获取pdf文件, 将其中指定的页面转成图片.
 71             PDFRenderer renderer = new PDFRenderer(document);
 72             try {
 73                 this.image = renderer.renderImage(index, 1, ImageType.RGB);
 74             } catch (IOException e) {
 75                 e.printStackTrace();
 76             }
 77 
 78         }
 79 
 80         @Override
 81         public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
 82             long start1 = System.currentTimeMillis();
 83             Graphics2D g2d = (Graphics2D) graphics.create();
 84             Paint paint = g2d.getPaint();
 85 
 86             int width = this.image.getWidth();
 87             int height = this.image.getHeight();
 88 
 89             Shape shape = new Rectangle2D.Double(0, 0, width, height);
 90             g2d.setPaint(createPaint(shape, StableUtils.isNotSupportARGB(g2d), image, width, height));
 91             g2d.fill(shape);
 92             g2d.setPaint(paint);
 93             g2d.dispose();
 94             long end1 = System.currentTimeMillis();
 95             System.out.println("打印第 " + (pageIndex + 1) + "页 耗时 : " + (end1 - start1) +" 毫秒 ");
 96             return Printable.PAGE_EXISTS;
 97         }
 98 
 99         private Paint createPaint(Shape shape, boolean isNotSupportARGB, BufferedImage image, int width, int height) {
100             Rectangle2D rec2D = shape.getBounds2D();
101             if ((int) rec2D.getWidth() <= 0) {
102                 rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth() + 40, rec2D.getHeight());
103             }
104             if ((int) rec2D.getHeight() <= 0) {
105                 rec2D.setRect(rec2D.getX(), rec2D.getY(), rec2D.getWidth(), rec2D.getHeight() + 40);
106             }
107             BufferedImage buffered = new BufferedImage((int) rec2D.getWidth(), (int) rec2D.getHeight(), isNotSupportARGB ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
108             Graphics2D g2 = buffered.createGraphics();
109             GraphHelper.paintImage(g2, (int) rec2D.getWidth(), (int) rec2D.getHeight(), image,
110                     Constants.IMAGE_CENTER , Constants.LEFT, Constants.TOP, width, height, isNotSupportARGB);
111 
112             g2.dispose();
113 
114             return new TexturePaint(buffered, rec2D);
115         }
116     }
117 
118 }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-12-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
编辑精选文章
换一批
微信小程序 带参二维码 纯Java实现
本文原创首发CSDN,链接 https://blog.csdn.net/qq_41464123/article/details/106335476 ,作者博客https://blog.csdn.net/qq_41464123 ,转载请带上本段内容,尤其是脚本之家、码神岛等平台,谢谢配合。 ----
Designer 小郑
2023/08/01
3620
微信小程序 带参二维码 纯Java实现
BufferedImage 将照片logo添加到二维码中间
猫头虎
2024/04/08
1750
BufferedImage 将照片logo添加到二维码中间
JAVA 将图片剪裁成圆形,并在圆形外带有白边
最近在做关于社交项目时,用到了二维码中间带图片logo的功能,但是要求图片为圆形,于是找到了java剪裁图片为圆形的工具类,并同时在圆形外围带有白边,不多说,直接上代码:
一诺千金
2020/04/30
5.4K1
Java如何实现二维码?【附源码】
第一步首先创建一个普通的 Maven 项目,然后要实现二维码功能,我们肯定要使用别人提供好的 Jar 包,这里我用的是 google 提供的 jar,pom.xml 文件配置如下:
好好学java
2020/12/21
1.6K0
Java如何实现二维码?【附源码】
Java 生成透明图片
设置图片透明import org.apache.commons.io.FilenameUtils;import org.apache.commons.io.IOUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.imageio.ImageIO;import javax.imageio.stream.ImageOutputStream;import javax.swing.\*;import java.awt.\*
IT小马哥
2022/12/31
1.2K0
java贪吃蛇小游戏(详解)[通俗易懂]
首先给出代码下载地址(含素材):https://share.weiyun.com/8hkvy1Ja
全栈程序员站长
2022/09/07
1.8K0
java贪吃蛇小游戏(详解)[通俗易懂]
java 利用 pdfbox 实现PDF转为图片
当时放到测试环境后一直显示乱码,看了下报错是说字体不存在。第一个想法是在主机上安装字体,但是又有问题了,生产不可能这样吧,运维也不同意啊。
Li_XiaoJin
2022/06/10
4.1K0
java 利用 pdfbox 实现PDF转为图片
mapboxGL中sprite生成与引用
用过mapboxGL的都知道里面有个叫做sprite的配置,它的主要用途就是地图上渲染图标的,但是大多数情况下我们需要自定义图标的,我们该怎么办呢,莫着急,牛老师有招,本文告诉你如何通过几行简单的java代码实现,用引用到我们的地图中。
牛老师讲GIS
2020/06/11
1.2K0
JavaUtil_03_图片处理工具类
 一、源码 功能:缩放图像、切割图像、图像类型转换、彩色转黑白、文字水印、图片水印等 package com.ray.dingtalk.util; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; i
shirayner
2018/08/10
1K0
java 图片加水印(图片或者文本)
对于上传的图片,有时候我们需要加上水印来标识图片的来源,以下java代码用来处理图片加文字和图片水印
日薪月亿
2019/05/14
3.5K0
Google zxing 生成带logo的二维码图片
SmileNicky
2023/10/19
4680
Google zxing 生成带logo的二维码图片
基于Java实现图像浏览器的设计与实现
推荐一个网站给想要了解或者学习人工智能知识的读者,这个网站里内容讲解通俗易懂且风趣幽默,对我帮助很大。我想与大家分享这个宝藏网站,请点击下方链接查看。 https://www.captainbed.cn/f1
鲜于言悠
2024/07/03
2410
基于Java实现图像浏览器的设计与实现
Java 2022圣诞树+2023元旦倒计时打包一起领走
2022最后一个月充满了期待,平安夜、圣诞节、元旦节;2023年也是一个早年,因此关于程序方面的浪漫,大家应该趁早准备。下面我将分享一个元旦的倒计时和圣诞树的绘制核心代码。大家可以依据自身的需求,稍微调整即可用。
非喵鱼
2022/12/14
1K0
Java 2022圣诞树+2023元旦倒计时打包一起领走
java——记录一次条形码、二维码、订单自动生成的制作
链接:https://pan.baidu.com/s/12mJTx7TkbK2HiWDgcT_jbQ 提取码:di1y
不愿意做鱼的小鲸鱼
2022/09/26
1.3K0
java——记录一次条形码、二维码、订单自动生成的制作
回敬Python蹭女神热度助发朋友圈,Java实现头像分成九宫图,再生成拼图头像
于是,我点开文章后,大概看了下文章的意思,其实就是把一个图片分成九宫图,即拼图的碎片,既然Python都能实现,作为回应,java必然也是可以做到的。
软件测试君
2020/07/31
8160
回敬Python蹭女神热度助发朋友圈,Java实现头像分成九宫图,再生成拼图头像
图片添加二维码水印教程
继之前博客PDF添加二维码水印教程:https://smilenicky.blog.csdn.net/article/details/91655064, 本博客介绍一下用jdk awt实现图片加文字水印和图片水印的方法
SmileNicky
2019/06/15
1.1K0
SpringMVC框架开发登录界面的验证码
本博客介绍如何开发登录界面的验证码 先写个验证码生成的Controller类: package com.appweb.controller.login; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.font.FontRenderContext; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedI
SmileNicky
2019/01/17
1.6K0
二维码服务拓展(支持logo,圆角logo,背景图,颜色配置)
二维码的基础服务拓展 zxing 提供了二维码一些列的功能,在日常生活中,可以发现很多二维码并不仅仅是简单的黑白矩形块,有的添加了文字,加了logo,定制颜色,背景等,本片博文则着手于此,进行基础服
一灰灰blog
2018/02/06
2.7K0
二维码服务拓展(支持logo,圆角logo,背景图,颜色配置)
【果壳信奥编程】纯 JAVA 实现植物大战僵尸
一枚大果壳
2024/05/18
1500
【果壳信奥编程】纯 JAVA 实现植物大战僵尸
Java文字转图片防爬虫
最近部分页面数据被爬虫疯狂的使用,主要就是采用动态代理IP爬取数据,主要是不控制频率,这个最恶心。因为对方是采用动态代理的方式,所以没什么特别好的防止方式。
conanma
2021/12/06
7K0
推荐阅读
相关推荐
微信小程序 带参二维码 纯Java实现
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验