Java實現pdf中動態插入圖片

今天接到一個需求,需要在pdf中的簽名處,插入簽名照片,但簽名位置不固定,話不多說上代碼:

1、首先引入itextpdf依賴包:

        <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency>

2、具體實現邏輯如下:

	/*** description PDF插入圖片(根據關鍵字位置動態插入)** @author yanzy* @version 1.0* @date 2025/3/27 17:26*/public static void imgToPdf2(String pdfPath, String imagePath, String outputPath, String keyword) {try {// 讀取原始PDFPdfReader reader = new PdfReader(pdfPath);FileOutputStream fos = new FileOutputStream(outputPath);PdfStamper stamper = new PdfStamper(reader, fos);// 遍歷PDF每一頁,查找關鍵字并插入簽名圖片Boolean keyBool = true;for (int i = 1; i <= reader.getNumberOfPages(); i++) {// 獲取當前頁面的文本和坐標信息List<Position> positions = getPositions(reader, i);// 合并連續文本塊StringBuilder combinedText = new StringBuilder();List<Position> textChunks = new ArrayList<>();for (Position pos : positions) {combinedText.append(pos.getText());textChunks.add(pos);}// 查找關鍵字在整個文本中的位置String fullText = combinedText.toString();int index = fullText.indexOf(keyword);if (index != -1) {// 獲取關鍵字起始位置Position endPos = findPositionByIndex(textChunks, index + keyword.length() - 1);// 計算插入坐標(取結束位置右側)float imgX = endPos.getX() + 20; // 橫縱標,右側偏移20單位float imgY = endPos.getY() - 20; // 縱坐標,向下移動20單位log.info("關鍵字位置 -> X:{}  Y: {} | 圖片位置 -> X: {}  Y:{}", endPos.getX(), endPos.getY(), imgX, imgY);// 添加圖片Image img = Image.getInstance(imagePath);// 圖片尺寸img.scaleToFit(100, 50);// 設置圖片的插入位置(X,Y坐標)img.setAbsolutePosition(imgX, imgY);// PdfStamper:直接修改原始PDF,避免圖層順序問題PdfContentByte canvas = stamper.getOverContent(i);canvas.addImage(img);keyBool = false;}}if (keyBool) {throw new Exception("未找到關鍵字位置!");}stamper.close();reader.close();log.info("圖片插入成功!");} catch (Exception e) {e.printStackTrace();log.error("pdf插入圖片失敗! errMsg: {}", e.getMessage());}}/*** description 根據文本索引找到對應位置** @author yanzy* @version 1.0* @date 2025/3/27 17:26*/private static Position findPositionByIndex(List<Position> chunks, int targetIndex) {int currentIndex = 0;for (Position chunk : chunks) {int chunkLength = chunk.getText().length();if (currentIndex + chunkLength > targetIndex) {return chunk;}currentIndex += chunkLength;}return chunks.get(chunks.size() - 1);}/*** description 獲取PDF頁面的所有文本位置** @author yanzy* @version 1.0* @date 2025/3/27 17:26*/private static List<Position> getPositions(PdfReader reader, int pageNumber) throws Exception {List<Position> positions = new ArrayList<>();// 創建PdfContentByte和RenderListener來提取文本PdfReaderContentParser parser = new PdfReaderContentParser(reader);parser.processContent(pageNumber, new RenderListener() {@Overridepublic void beginTextBlock() {}@Overridepublic void endTextBlock() {}@Overridepublic void renderText(TextRenderInfo renderInfo) {String text = renderInfo.getText();float x = renderInfo.getBaseline().getStartPoint().get(0);float y = renderInfo.getBaseline().getStartPoint().get(1);positions.add(new Position(x, y, text));}@Overridepublic void renderImage(ImageRenderInfo renderInfo) {}});return positions;}public static void main(String[] args) {// 輸入PDF路徑String srcPdf = "E://test.pdf";// 輸出PDF路徑String destPdf = "E://output_image.pdf";// 圖片路徑String imagePath = "E://test.jpg";// 關鍵字String keyword = "本人簽名:";//imgToPdf(srcPdf, imagePath, destPdf);imgToPdf2(srcPdf, imagePath, destPdf, keyword);}
/*** description pdf中的文本坐標** @author yanzy* @date 2025/3/28 15:36*/
public class Position {private final float x;private final float y;private final String text;public Position(float x, float y, String text) {this.x = x;this.y = y;this.text = text;}public float getX() {return x;}public float getY() {return y;}public String getText() {return text;}}

3、下面是pdf的內容:
在這里插入圖片描述
4、運行程序后的結果:
在這里插入圖片描述
5、可以看到簽名照片已經成功加上了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75878.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75878.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75878.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenCV 圖形API(2)為什么需要圖形API?

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 G-API背后的動機 G-API模塊為OpenCV帶來了基于圖的執行模型。本章簡要描述了這種新模型如何在兩個方面幫助軟件開發者&#xff1a;優化和移植圖像處理算法…

基于Spring AI開發本地Jenkins MCP Server服務

前言 首先介紹下MCP是什么&#xff1f; MCP是由開發了 Claude 模型的 Anthropic 公司2024年12月提出并開源的一項開放標準&#xff0c;全稱&#xff1a;Model Context Protocol&#xff0c;它是一個開放協議&#xff0c;它使 LLM 應用與外部數據源和工具之間的無縫集成成為可能…

vcpkg安裝指定版本的庫

一.vcpkg安裝 使用git將vcpkg源碼克隆到本地制定目錄&#xff08;D:\vcpkg&#xff09;&#xff0c;并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下圖&#xff1a; 二.安…

數據結構C語言練習(單雙鏈表)

本篇練習題(單鏈表)&#xff1a; 1.力扣 203. 移除鏈表元素 2.力扣 206. 反轉鏈表 3.力扣 876. 鏈表的中間結點 4.力扣 21. 合并兩個有序鏈表 5. 牛客 鏈表分割算法詳解 6.牛客 鏈表回文結構判斷 7. 力扣 160. 相交鏈表 8. 力扣 141 環形鏈表 9. 力扣 142 環形鏈表 II…

nginx部署前端項目(linux、docker)

引言 在CentOS 7系統上使用docker安裝nginx&#xff0c;使用nginx部署一個由Vue開發、打包的項目 docker安裝nginx 這里不多贅述&#xff0c;直接上docker-compose.yml代碼 nginx:container_name: nginximage: nginx:1.27.2ports:- "80:80"volumes:- /docker/ngin…

WPF ContentPresenter詳解2

ContentPresenter與ContentControl的區別 ContentControl 和 ContentPresenter 是 WPF 中兩個相關的控件&#xff0c;但它們在用途和功能上有一些關鍵的區別。理解這兩者的區別和聯系有助于更好地設計和開發用戶界面。 1. 類層次結構 ContentControl&#xff1a;位于 WPF 控件…

【HTML5游戲開發教程】零基礎入門合成大西瓜游戲實戰 | JS物理引擎+Canvas動畫+完整源碼詳解

《從咖啡杯到財務自由&#xff1a;一個程序員的合成之旅——當代碼遇上物理引擎的匠心之作》 &#x1f31f; 這是小游戲開發系列的第四篇送福利文章&#xff0c;感謝一路以來支持和關注這個項目的每一位朋友&#xff01; &#x1f4a1; 文章力求嚴謹&#xff0c;但難免有疏漏之…

鴻蒙OS 5.0 服務能力框架深入剖析

鴻蒙OS 5.0 服務能力框架中關鍵類的作用分析 1\. 鴻蒙OS 5.0 服務能力框架導論 鴻蒙OS 5.0&#xff0c;亦稱鴻蒙智聯 5 1&#xff0c;標志著華為在分布式操作系統領域邁出的重要一步。與早期版本采用兼容安卓的AOSP層、Linux內核以及LiteOS內核不同&#xff0c;鴻蒙OS 5.0 專注…

RTMP推流+EasyDSS云服務+邊緣AI分析的無人機監控系統設計

在現代科技不斷發展的背景下&#xff0c;無人機技術已經廣泛應用于各個領域&#xff0c;從航拍攝影到工業巡檢&#xff0c;從農業監測到應急救援&#xff0c;無人機以其高效的工作能力&#xff0c;為人們的生活和工作帶來了諸多便利與創新&#xff0c;而其視頻傳輸與分析系統更…

HCIP(VLAN綜合實驗)

實驗拓補圖 實驗分析 一、實驗目的 掌握VLAN的創建和配置方法理解VLAN在局域網中的作用學習如何通過VLAN實現網絡隔離和通信 二、實驗環境 交換機&#xff08;SW1、SW2、SW3&#xff09;個人電腦&#xff08;PC1、PC2、PC3、PC4、PC5、PC6&#xff09;路由器&#xff08;R1…

Linux系統編程 | 線程的基本概念

&#x1f493;個人主頁&#xff1a;mooridy &#x1f493;專欄地址&#xff1a;Linux 關注我&#x1f339;&#xff0c;和我一起學習更多計算機的知識! &#x1f51d;&#x1f51d;&#x1f51d; 什么是線程 程序中的一個執行路線就叫做線程 一個進程至少要有一個執行線程,單…

小林coding-12道Spring面試題

1.說一下你對 Spring 的理解?spring的核心思想說說你的理解&#xff1f; 2.Spring IoC和AOP 介紹一下?Spring的aop介紹一下?IOC和AOP是通過什么機制來實現的?怎么理解SpringIoc&#xff1f;依賴倒置&#xff0c;依賴注入&#xff0c;控制反轉分別是什么&#xff1f;依賴注…

第十二章——位運算

按位的與& 若x的第i位和y的第i位都是1&#xff0c;那么&#xff08;x&y&#xff09;1&#xff0c;否則&#xff08;x&y&#xff09; 0 應用&#xff1a;希望讓某一位或某些位為0 。取一個數中的一段。 按位的或| 若x的第i位1或y的第i位1&#xff0c;那么&…

計算機等級考試數據庫三級(筆記3)

插入 修改 現要創建一個具有如下功能的觸發器&#xff1a;每當在銷售表中插入一條銷售記錄時&#xff0c;修改商品表中對應商品的銷售總量&#xff0c;假設一次只插入一條銷售記錄。請補全下列代碼。CREATE TRIGGER tri insert on xx FOR xx AS xx 商品表 xx 銷售總量xx (SELEC…

【Leetcode 每日一題】2716. 最小化字符串長度

問題背景 給你一個下標從 0 0 0 開始的字符串 s s s&#xff0c;重復執行下述操作 任意 次&#xff1a; 在字符串中選出一個下標 i i i&#xff0c;并使 c c c 為字符串下標 i i i 處的字符。并在 i i i 左側&#xff08;如果有&#xff09;和 右側&#xff08;如果有&…

Flutter中實現拍照識題的功能

文章目錄 **1. 功能拆解****2. 具體實現步驟****(1) 拍照或選擇圖片****(2) 圖片預處理&#xff08;可選&#xff09;****(3) 文字識別&#xff08;OCR&#xff09;****(4) 數學公式識別 → LaTeX****方案1&#xff1a;Mathpix API&#xff08;高精度&#xff0c;付費&#xff…

【Mysql:內置函數】

日期函數&#xff1a; 查看當前日期&#xff1a; select current_date();查看當前時間&#xff1a; select current_time(); 查看當前時間戳&#xff1a; select current_timestamp(); 計算兩個日期的差值&#xff1a; select datediff(date1,date2); 當前的日期時間&a…

71. 我的第一個Linux驅動實驗

一、字符設備驅動框架 字符設備驅動的編寫主要就是驅動對應的open、close、read。。。其實就是 file_operations結構體的成員變量的實現。 其中關于 C 庫以及如何通過系統調用“陷入” 到內核空間這個我們不用去管&#xff0c;我們重點關注的是應用程序和具體的驅動&#xff0…

jdk21使用Vosk實現語音文字轉換,免費的語音識別

1.下載vosk的model vosk官網&#xff1a;https://alphacephei.com/vosk/models 我這里使用較小的vosk-model-small-cn-0.22 2.添加相關pom文件 <!-- 獲取音頻信息 --><dependency><groupId>org</groupId><artifactId>jaudiotagger</artifac…

如何一鍵安裝所有Python項目的依賴!

在開發項目時&#xff0c;常常需要在多個環境中安裝各種依賴。對開發者來說&#xff0c;每次手動一個個安裝這些依賴是不是很麻煩&#xff1f;&#x1f605; 其實有個超簡單的辦法&#xff01;只需要一個腳本&#xff0c;就能快速解決問題&#xff01;&#x1f4a1; 這就是我們…