通过itextpdf操作PDF,向PDF文件最后一页添加图片(缩放图片并判断最后一页是否能放下图片)

  • 本人第一篇博客,哈哈!第一次接触itextpdf,想实现将图片向PDF尾部追加(判断原页面使用情况,图片缩放后是否可以放的下,放不下时新增页面插入图片),网上博客也看了很多,没有符合我的预期的(可能我没有发现吧,哈哈,百度也是个技术活),就研究了两天,写了这个,菜鸡一枚,希望多多交流哈!有代码优化及重构思路也希望可以指点一二!
    • pom.xml
    • ITextTest 测试类
    • PdfHandler类
      • 1.获取到最后一页(可以是任意页)document,拿到对应PDF页面宽度和高度;
      • 2.通过pdfRenderListener 处理最后一页所有文本内容,记录文本对应坐标,获取页面内容尾部高度;
      • 3.压缩图片:根据页面宽度和图片宽度进行图片缩放,过程中页边距按默认36进行计算,如需精确计算页边距可以通过PdfRenderListener记录的文本横坐标进行判定(不清楚是否itext有对应的方法可以直接调用获取);
      • 4.通过文本尾部高度-文本与插入图片保持的上下间距(自定义为10)-压缩后图片高度>0判断是否图片可以插入(没有考虑下页边距);
      • 5.当前页插入图片或新开一页插入图片
    • PdfRenderListener(实现RenderListener,重写renderText方法)
    • RectangeInfo

本人第一篇博客,哈哈!第一次接触itextpdf,想实现将图片向PDF尾部追加(判断原页面使用情况,图片缩放后是否可以放的下,放不下时新增页面插入图片),网上博客也看了很多,没有符合我的预期的(可能我没有发现吧,哈哈,百度也是个技术活),就研究了两天,写了这个,菜鸡一枚,希望多多交流哈!有代码优化及重构思路也希望可以指点一二!

pom.xml

   <!-- 核心依赖包 --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.2</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><!-- 辅助工具包 --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.1.1-jre</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.76</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.13</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version><scope>provided</scope></dependency>

ITextTest 测试类

package com.dyx.springbootbase;import com.dyx.springbootbase.pdf.itext.PdfHandler;
import java.io.IOException;
import org.junit.Test;/*** @author duyunxi* @sign 世人莫羡长安景,风雨楼外多风雨* @date 2021-10-17 10:07*/
public class ITextTest {private static String filePath = "C:\\Users\\TR\\Desktop\\java\\java电子书\\深入理解Java虚拟机:JVM高级特性与最佳实践(最新第三版).pdf";private static String filePath1 = "C:\\Users\\TR\\Desktop\\java\\java电子书\\阿里巴巴Java开发手册泰山版.pdf";private static String imageName = "C:\\Users\\TR\\Pictures\\1.jpg";@Testpublic void insertToPdf() {try {PdfHandler pdfHandler = new PdfHandler(filePath, imageName);pdfHandler.addImageToPdf();// 关流,删除临时文件pdfHandler.close();} catch (IOException e) {e.printStackTrace();}}
}

PdfHandler类

1.获取到最后一页(可以是任意页)document,拿到对应PDF页面宽度和高度;

2.通过pdfRenderListener 处理最后一页所有文本内容,记录文本对应坐标,获取页面内容尾部高度;

3.压缩图片:根据页面宽度和图片宽度进行图片缩放,过程中页边距按默认36进行计算,如需精确计算页边距可以通过PdfRenderListener记录的文本横坐标进行判定(不清楚是否itext有对应的方法可以直接调用获取);

4.通过文本尾部高度-文本与插入图片保持的上下间距(自定义为10)-压缩后图片高度>0判断是否图片可以插入(没有考虑下页边距);

5.当前页插入图片或新开一页插入图片

package com.dyx.springbootbase.pdf.itext;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;import com.itextpdf.text.BadElementException;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;/*** @author duyunxi* @sign 世人莫羡长安景,风雨楼外多风雨* @date 2021-10-16 22:21*/
public class PdfHandler {private static final int WORD_IMAGE_SPACE = 10;private String targetPath = "D:\\target";private String targetImagePath = "D:\\target";private String filePath;private String imagePath;private int pages;private PdfReader reader;private Document document;private PdfStamper stamper;private FileOutputStream fos;public PdfHandler(String filePath, String imagePath) throws IOException {this.filePath = filePath;this.imagePath = imagePath;this.targetPath = targetPath + File.separator + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".pdf";this.targetImagePath =targetImagePath + File.separator + DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".jpg";this.reader = new PdfReader(filePath);this.pages = reader.getNumberOfPages();this.fos = new FileOutputStream(targetPath);}/*** 在pdf最后一页添加图片*/public void addImageToPdf() {try {// 获取最后一页文档对象进行判断document = new Document(reader.getPageSize(pages));// Create a stamper that will copy the document to a new filePdfReaderContentParser contentParser = new PdfReaderContentParser(reader);PdfRenderListener pdfRenderListener = new PdfRenderListener();// 处理最后一页(pages) pdfRenderListener = contentParser.processContent(pages, pdfRenderListener);RectangeInfo rectangeInfo = pdfRenderListener.getRectangeInfo();// 最后一页实际文字内容到达的纵坐标位置float bottomY = rectangeInfo.getRectangeY();// 如果图片大小超过PDF宽度,对图片按宽度进行等比压缩(一般图片宽度大于高度)Image oldImage = Image.getInstance(imagePath);// 图片宽度float imgWidth = oldImage.getWidth();// pdf宽度float width = document.getPageSize().getWidth();float scale = scaleImageByWidth(imagePath, targetImagePath, width, imgWidth);// 压缩后图片高度float scaleHeight = scale * oldImage.getHeight();// Can't fit the picture on the current pageif (bottomY - WORD_IMAGE_SPACE < scaleHeight) {float height = document.getPageSize().getHeight();// add image to the new pageaddImgToNewPage(filePath, targetPath, targetImagePath, width, height);} else {// add image on the current page// 文字到达的纵坐标位置-文字与图片间距10-压缩后图片高度float imageY = bottomY - WORD_IMAGE_SPACE - scaleHeight;addImageToBottom(filePath, targetImagePath, width, imageY);}} catch (BadElementException | IOException e) {e.printStackTrace();}}/*** when the imgWidth more than the width,scale image, return the scale** @param imagePath*            image path* @param targetImage*            target image* @param width*            pdf width* @param imgWidth*            img width* @return scale*/public float scaleImageByWidth(String imagePath, String targetImage, float width, float imgWidth) {// 缩放比例float div = 1;// 图片宽度过长时进行压缩处理if (width < imgWidth) {// 一般PDF页边距为36,减去两边的页边距72div = (float)NumberUtil.div(width - 72, imgWidth, 4);}ImgUtil.scale(FileUtil.file(imagePath), FileUtil.file(targetImage), div);return div;}/*** 添加图片到新页面** @param filePath*            文件路径* @param targetPath*            修改后pdf路径* @param imagePath*            压缩后图片路径* @param width*            pdf宽度* @param height*            pdf高度*/public void addImgToNewPage(String filePath, String targetPath, String imagePath, float width, float height) {try {stamper = new PdfStamper(reader, fos);// insert new pagestamper.insertPage(reader.getNumberOfPages() + 1, reader.getPageSizeWithRotation(1));// get new pagePdfContentByte under = stamper.getOverContent(reader.getNumberOfPages());Image image = Image.getInstance(imagePath);float imageX = (width - image.getWidth()) / 2;// PDF高度-图片高度-页面上边距float imageY = height - image.getHeight() - 36;// 设置图片坐标位置image.setAbsolutePosition(imageX, imageY);// 图片居中image.setAlignment(Image.ALIGN_MIDDLE);under.addImage(image);} catch (DocumentException | IOException e) {e.printStackTrace();}}/*** 添加图片到当前页面尾部** @param filePath*            文件路径* @param imagePath*            图片路径* @param width*            pdf宽度* @param imageY*            图片放置位置纵坐标*/private void addImageToBottom(String filePath, String imagePath, float width, float imageY) {try {stamper = new PdfStamper(reader, fos);Image img = Image.getInstance(imagePath);float imageX = (width - img.getWidth()) / 2;// 图片放置位置img.setAbsolutePosition(imageX, imageY);// set image in centerimg.setAlignment(Image.ALIGN_MIDDLE);// Text over the existing pagePdfContentByte over = stamper.getOverContent(pages);over.addImage(img);} catch (DocumentException | IOException e) {e.printStackTrace();}}public void close() {try {if (!Objects.isNull(stamper)) {stamper.close();}if (!Objects.isNull(document)) {document.close();}if (!Objects.isNull(fos)) {fos.close();}if (!Objects.isNull(reader)) {reader.close();}// 删除压缩产生的临时图片FileUtil.del(targetImagePath);} catch (DocumentException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

PdfRenderListener(实现RenderListener,重写renderText方法)

package com.dyx.springbootbase.pdf.itext;import com.itextpdf.awt.geom.Rectangle2D;
import com.itextpdf.text.pdf.parser.ImageRenderInfo;
import com.itextpdf.text.pdf.parser.RenderListener;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import java.util.ArrayList;
import java.util.List;/*** @author duyunxi* @sign 世人莫羡长安景,风雨楼外多风雨* @date 2021-10-16 21:10*/
public class PdfRenderListener implements RenderListener {// 用于记录页面文字内容对应的文字横纵坐标及文字宽高private List<RectangeInfo> rectangeInfos = new ArrayList<>();// private RectangeInfo rectangeInfo;public List<RectangeInfo> getRectangeInfos() {return rectangeInfos;}public void setRectangeInfos(List<RectangeInfo> rectangeInfos) {this.rectangeInfos = rectangeInfos;}public RectangeInfo getRectangeInfo() {return rectangeInfo;}@Override// 开始读取文字内容时public void beginTextBlock() {}@Override// 读取文字内容,经测试,读取文字顺序是按页眉、页脚、正文顺序读取//即使页面包含图片,读取结束的text对应的也是整个页面所有内容的终止坐标点// 本文只关注纵坐标Y的位置 ,如需精确页面页边距可通过集合记录横坐标X确定左右页边距大小public void renderText(TextRenderInfo renderInfo) {String text = renderInfo.getText();Rectangle2D.Float boundingRectange =renderInfo.getBaseline().getBoundingRectange();RectangeInfo rectangeInfo =        RectangeInfo.builder().rectangeX(boundingRectange.x).rectangeY(boundingRectange.y).build();rectangeInfo.setContent(text);rectangeInfos.add(rectangeInfo);}@Overridepublic void endTextBlock() {rectangeInfo = rectangeInfos.get(rectangeInfos.size() - 1);}@Override// 对页面中图片进行操作public void renderImage(ImageRenderInfo renderInfo) {}
}

RectangeInfo

package com.dyx.springbootbase.pdf.itext;import lombok.Builder;
import lombok.Data;
import lombok.ToString;/*** 记录文本内容坐标信息* * @author duyunxi* @sign 世人莫羡长安景,风雨楼外多风雨* @date 2021-10-16 21:14*/
@Data
@ToString
@Builder
public class RectangeInfo {private String content;private float rectangeX;private float rectangeY;
}

通过itextpdf操作PDF,动态向PDF文件最后一页添加图片相关推荐

  1. Qt中为工程添加资源文件、给按钮添加图片

    Qt中为工程添加资源文件.给按钮添加图片 1.使用QIcon类.代码如下: QIcon icon;icon.addFile(tr("res/icon/wall.png"));ui- ...

  2. JAVA PdfBox库提取PDF文件某一页转为图片

    Apache PDFBox 库是一个开源.用于操作 PDF 文档的 Java 工具库.PDFBox 允许创建新的 PDF 文档.操作现有文档,以及从文档中提取内容. 获取 Apache PDFBox ...

  3. html 如何把图片作为背景_办公软件操作技巧062:如何给word文档添加图片背景

    在日常工作中,我们经常用word编辑文档,有时为了使文档更加的美观大气,可以给文档添加上背景图片,今天就来和大家分享如何在word中给文档添加图片背景. 方法一:填充图片法 单击"页面布局& ...

  4. Python把PDF文件中每页内容分离为独立图片文件

    封面图片:<Python程序设计实验指导书>(ISBN:9787302525790),董付国,清华大学出版社 图书详情(京东): ============== 问题描述:把PDF文件转换为 ...

  5. PDF文件怎么添加图片 如何编辑PDF图片

    在编辑文档的时候总会要插入一些图片内容,然后对图片进行一些简单的编辑和设置.像word.ppt这类常见的文档自然不必多少,大家也都知道怎样去操作.但是对PDF这种文档还是有很多人不熟悉的.那么在PDF ...

  6. java操作图片集合(添加图片水印、文字水印,文字生成图片,图片转pdf等)

    花不多说 ,上代码 简单文字水印 // path 为原图片地址, outPath则是输出新图片地址public static void addWatermark(String path, String ...

  7. 学生专用计算机操作手册,学生综合素质评价平台操作手册(PC版).pdf

    学生综合素质评价平台 用户操作手册 (PC 版 1.0) 201X 年 XX 月 XX 日发布 201X 年 XX 月 XX 日实施 目录 目录 1 1 引言 1 1.1 编写目的 1 1.2 项目背 ...

  8. java在linux生成pdf文件,从 Java 应用程序动态生成 PDF 文件

    简介: 如果您的应用程序需要动态生成 PDF 文档,那么您需要 iText 库.开源的 iText 库使得 PDF 的创建变得轻松易行.本文介绍了 iText 并提供了一个使用它从 Java 技术应用 ...

  9. java设置pdf不可编辑_Java动态生成pdf文件(使用itext编辑pdf)

    一.创建pdf模板 使用PDFelement制作pdf模板(数据域的名称对应后面插入的key) 二.导入maven依赖 com.itextpdf itextpdf 5.5.13 com.itextpd ...

最新文章

  1. jquery入门 修改网页背景颜色
  2. C#语言与面向对象技术(2)
  3. clickhouse 分布式数据库 简介
  4. openStack高可用性和灾备方案
  5. visio中UML在活动图中指示判定
  6. 经典的C++面试题目
  7. c语言错误指导,c语言编程指导.pdf
  8. linux中tcp连接内核参数调优somaxconn
  9. firewalld/iptables防火墙维护和状态查询命令(防火墙重载,区域操作命令,开启服务或端口,堵塞端口,iptables规则添加和删除)
  10. JEP 181不兼容,嵌套类/ 2
  11. 1005 继续(3n+1)猜想 (25分)
  12. Seata多微服务互相调用_全局分布式事物使用案例_Order-Module order微服务的配置搭建_写代码下---微服务升级_SpringCloud Alibaba工作笔记0062
  13. 实现一个高效C++委托类(多分派)
  14. 图像局部特征(十三)--FREAK特征
  15. oracle impdp 39002,expdp/impdp ORA-39002ORA-39166 | 学步园
  16. 如何在 Mac 上右键单击?
  17. Hbuilder We're sorry
  18. 《时代三部曲》感悟四
  19. 在linux下成功写Bingo游戏
  20. 用vc++穷举windows应用程序密码

热门文章

  1. 从零开始 飞机大战(五)实现子弹定位和动画
  2. BCK生态链第一条价值共识侧链CK正式上线
  3. 根据地址获取坐标经纬度
  4. 三维人脸重建 (一)
  5. 计算机毕业设计ssm客房订餐系统s2whx系统+程序+源码+lw+远程部署
  6. AD18无法仿真问题的解决
  7. Linux 终端生存指南
  8. springboot中整合mybatis及简单使用
  9. python项目练习四:新闻聚合
  10. 数字IC设计学习笔记_静态时序分析STA_伪路径False Paths