Java使用pdfbox實(shí)現(xiàn)給pdf文件加圖片水印
引入依賴
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.27</version> </dependency>
代碼
調(diào)節(jié)參數(shù):圖片寬高,旋轉(zhuǎn)角度,幾行幾列 等等
package sjp.demo.workutils.utils; import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.graphics.blend.BlendMode; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.util.Matrix; import java.io.File; import java.io.IOException; public class PdfUtils { public static void main(String[] args) throws IOException { String file = "D:\\workspaces\\demo\\sjp-work-utils\\src\\main\\resources\\pdf\\阿拉丁統(tǒng)計(jì)平臺(tái)SDK接入指南.pdf"; String imgPath = "D:\\workspaces\\demo\\sjp-work-utils\\src\\main\\resources\\imgs\\logo.png"; addImgWatermark(file, imgPath); } public static void addImgWatermark(String filePath, String imgPath) throws IOException { String name = filePath.substring(filePath.lastIndexOf(File.separator), filePath.lastIndexOf(".pdf")); String folder = filePath.substring(0, filePath.lastIndexOf(File.separator)); File file = new File(filePath); try (PDDocument doc = PDDocument.load(file)) { PDImageXObject pdImage = PDImageXObject.createFromFile(imgPath, doc); WatermarkOptions options = new WatermarkOptions() .size(120, 60) .padding(20) .layout(4, 3) // 建議0-90度 .rotate(30); for (PDPage page : doc.getPages()) { addImgWatermark(doc, page, pdImage, options); } doc.save(folder + File.separator + name + "_WaterMark.pdf"); } } private static void addImgWatermark(PDDocument doc, PDPage page, PDImageXObject pdImage, WatermarkOptions options) throws IOException { try ( PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true) ) { float width = page.getMediaBox().getWidth(); float height = page.getMediaBox().getHeight(); // System.out.println("width=" + width + ",height=" + height); //有一些pdf頁面是有角度翻轉(zhuǎn)的,修正一下 int rotation = page.getRotation(); // System.out.println("page.getRotation()=" + rotation); switch (rotation) { case 90: width = page.getMediaBox().getHeight(); height = page.getMediaBox().getWidth(); cs.transform(Matrix.getRotateInstance(Math.toRadians(90), height, 0)); break; case 180: cs.transform(Matrix.getRotateInstance(Math.toRadians(180), width, height)); break; case 270: width = page.getMediaBox().getHeight(); height = page.getMediaBox().getWidth(); cs.transform(Matrix.getRotateInstance(Math.toRadians(270), 0, width)); break; default: break; } PDExtendedGraphicsState gs = new PDExtendedGraphicsState(); gs.setNonStrokingAlphaConstant(0.2f);// 設(shè)置透明度 gs.setAlphaSourceFlag(true); gs.setBlendMode(BlendMode.NORMAL); cs.setGraphicsStateParameters(gs); int row = options.row; int column = options.column; float imgWidth = options.width; float imgHeight = options.height; float padding = options.padding; int degree = options.degree; // 計(jì)算獲得每個(gè)單元格的寬高 float cellWidth = (width - padding * 2) / column; float cellHeight = (height - padding * 2) / row; // System.out.println("cellWidth=" + cellWidth + ",cellHeight=" + cellHeight); // 偏移量,如果單元格寬高大于圖片寬高,這可以使圖片居中 float xOffset = padding + (cellWidth - imgWidth) / 2; float yOffset = padding + (cellHeight - imgHeight) / 2; float x; float y; for (int i = 0; i < row; i++) { y = i * cellHeight + yOffset; for (int j = 0; j < column; j++) { x = j * cellWidth + xOffset; // 旋轉(zhuǎn)導(dǎo)致的x位置修正 x += Math.sin(Math.toRadians(degree)) * imgHeight; // System.out.println((int) x + "," + (int) y); Matrix matrix = new Matrix(); // 先移位 matrix.translate(x, y); // 旋轉(zhuǎn) matrix.rotate(Math.toRadians(degree)); // 修改尺寸(必須在旋轉(zhuǎn)后面,否則會(huì)變形) matrix.scale(imgWidth, imgHeight); // 畫圖 cs.drawImage(pdImage, matrix); } } } } static class WatermarkOptions { /** * 邊距 */ float padding = 20; /** * 圖片寬度 */ float width; /** * 圖片高度 */ float height; /** * 旋轉(zhuǎn)角度 */ int degree = 0; /** * 行數(shù) */ int row = 1; /** * 列數(shù) */ int column = 1; public WatermarkOptions() { } public WatermarkOptions padding(int p) { if (p < 10) { throw new IllegalArgumentException("邊距不能小于0"); } this.padding = p; return this; } public WatermarkOptions layout(int row, int column) { if (row <= 0 || column <= 0) { throw new IllegalArgumentException("行數(shù)或列數(shù)必須大于0"); } this.row = row; this.column = column; return this; } public WatermarkOptions size(float width, float height) { this.width = width; this.height = height; return this; } public WatermarkOptions rotate(int degree) { this.degree = degree; return this; } } }
效果
到此這篇關(guān)于Java使用pdfbox實(shí)現(xiàn)給pdf文件加圖片水印的文章就介紹到這了,更多相關(guān)Java pdfbox添加圖片水印內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中連接數(shù)據(jù)庫方式詳細(xì)步驟記錄
這篇文章主要介紹了Java中連接數(shù)據(jù)庫方式的詳細(xì)步驟,包括添加依賴、建立連接、執(zhí)行SQL語句、處理結(jié)果集和關(guān)閉連接,還討論了數(shù)據(jù)庫連接池的使用,需要的朋友可以參考下2025-01-01spring Security的自定義用戶認(rèn)證過程詳解
這篇文章主要介紹了spring Security的自定義用戶認(rèn)證過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03Spring MVC 中攔截器的使用示例詳解"攔截器基本配置"和 &q
Spring MVC 的攔截器作用是在請求到達(dá)控制器之前或之后進(jìn)行攔截,可以對請求和響應(yīng)進(jìn)行一些特定的處理,這篇文章主要介紹了Spring MVC 中的攔截器的使用“攔截器基本配置” 和 “攔截器高級(jí)配置”,需要的朋友可以參考下2024-07-07mybatis升級(jí)mybatis-plus時(shí)踩到的一些坑
這篇文章主要給大家介紹了關(guān)于mybatis升級(jí)mybatis-plus時(shí)踩到的一些坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09