Java使用pdfbox實(shí)現(xiàn)給pdf文件加圖片水印
更新時(shí)間:2022年11月14日 10:37:21 作者:初窺門徑
有時(shí)候需要給pdf加水印,市面上工具都是收費(fèi)的要會(huì)員,還是自食其力吧;嘗試過 spire.pdf.free 那個(gè)超過10頁(yè)就不行了!所以本文還是使用了pdfbox,感興趣的可以了解一下
引入依賴
<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頁(yè)面是有角度翻轉(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring?kafka?@KafkaListener詳解與使用過程
這篇文章主要介紹了spring-kafka?@KafkaListener詳解與使用,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-02-02Java位運(yùn)算和邏輯運(yùn)算的區(qū)別實(shí)例
Java位運(yùn)算和邏輯運(yùn)算的區(qū)別實(shí)例,請(qǐng)參考下面代碼,希望對(duì)你有所幫助2013-02-02Java數(shù)據(jù)結(jié)構(gòu)中圖的進(jìn)階詳解
在Java學(xué)習(xí)與應(yīng)用中,數(shù)據(jù)結(jié)構(gòu)無疑是每個(gè)人都要接觸的難點(diǎn),為了更好的學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)這一塊內(nèi)容,用圖來理解便是最好的方式,讓我們一起來了解本篇內(nèi)容圖的進(jìn)階2022-01-01如何使用Jenkins編譯并打包SpringCloud微服務(wù)目錄
這篇文章主要介紹了如何使用Jenkins編譯并打包SpringCloud微服務(wù)目錄,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11