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頁(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);
// 畫(huà)圖
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)文章
Java中連接數(shù)據(jù)庫(kù)方式詳細(xì)步驟記錄
這篇文章主要介紹了Java中連接數(shù)據(jù)庫(kù)方式的詳細(xì)步驟,包括添加依賴、建立連接、執(zhí)行SQL語(yǔ)句、處理結(jié)果集和關(guān)閉連接,還討論了數(shù)據(jù)庫(kù)連接池的使用,需要的朋友可以參考下2025-01-01
spring Security的自定義用戶認(rèn)證過(guò)程詳解
這篇文章主要介紹了spring Security的自定義用戶認(rèn)證過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)幸運(yùn)抽獎(jiǎng)功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03
Spring MVC 中攔截器的使用示例詳解"攔截器基本配置"和 &q
Spring MVC 的攔截器作用是在請(qǐng)求到達(dá)控制器之前或之后進(jìn)行攔截,可以對(duì)請(qǐng)求和響應(yīng)進(jìn)行一些特定的處理,這篇文章主要介紹了Spring MVC 中的攔截器的使用“攔截器基本配置” 和 “攔截器高級(jí)配置”,需要的朋友可以參考下2024-07-07
mybatis升級(jí)mybatis-plus時(shí)踩到的一些坑
這篇文章主要給大家介紹了關(guān)于mybatis升級(jí)mybatis-plus時(shí)踩到的一些坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09

