咖啡汪日志——JAVA导出pdf文件加水印 文字和图片、文字
hello,又大家见面了! 作为一只不是在戏精就是在戏精路上的哈士奇,今天要展示给大家的就是如何快捷地给pdf文件增加各种水印。嗷呜呜,前行万里,愿未来皆好。
主要解决问题如下:
1、自定义文字内容,颜色加水印。
2、自定义文字+自定义logo(需要设计小姐姐帮忙做出来)加水印。
3、自由控制水印间隔,包括纵向间隔与横向间隔均可调节。
4、导出水印文件可转为图片格式的pdf文件。
涉及的问题修复
系统本身缺少中文字体导致的报错,本汪提供了 AdobeSongStd-Light 字体安装包。
链接:https://pan.baidu.com/s/1EIhW6LMiLlsgchfOf1rU-Q?pwd=o51c
提取码:o51c
下载后解压即可得到该字体,window、linux下怎么安装,大家自行问度娘就行。
提供给大家的取色器,案例图片:
链接:https://pan.baidu.com/s/1f67q6np9nwja4aLXGXfi4w?pwd=u7c4
提取码:u7c4
完成效果如图:
代码内容:
pom.xml 中添加依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<!-- PDF文件字体 防止中文乱码 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
java工具类:
一共三个工具类:1、导出文字 2、导出文字+图片 3、可编辑pdf转图片型pdf
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JLabel;
/**
* @author yuezejian
* <p>描述: pdf文件加水印工具类
* <p>日期: 2023年2月24日 下午3:20:26
*/
public class IntegrationFileUtil {
private static final Logger logger = LoggerFactory.getLogger(IntegrationFileUtil.class);
/**
* @author yuezejian
* <p>描述: 给PDF添加水印仅文字
* <p>日期: 2023年2月24日 下午3:20:26
* @param inputFile 原文件路径+名称
* @param outputFile 添加水印后输出文件保存的路径+名称
* @param waterMarkName 添加水印的内容
* @param textH 文字水印区域高度
* @param textW 文字水印区域宽度
* @param fontAndSize 水印字体大小
* @param R red 色域
* @param G green 色域
* @param B B blue 色域
*/
public static void PDFAddWatermark(String inputFile,String outputFile, String waterMarkName, int textH, int textW, int fontAndSize, int R,int G, int B) {
try {
// 参数默认赋值
if (textH == 0) {
textH = 45;
}
if (textW == 0) {
textW = 100;
}
if (fontAndSize == 0) {
fontAndSize = 15;
}
if (R == 0) {
R = 2;
}
if (G == 0) {
G = 152;
}
if (B == 0) {
G = 246;
}
// 间隔距离
int interval = 30;
PdfReader reader = new PdfReader(inputFile);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
// 设置文字水印样式
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
// 设置字体颜色
BaseColor baseColor = new BaseColor(R,G,B);
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.8f);//改透明度
gs.setStrokeOpacity(0.4f);
int total = reader.getNumberOfPages() + 1;
JLabel label = new JLabel();
label.setText(waterMarkName);
PdfContentByte under;
// 添加多行文字水印
Rectangle pageRect = null;
label.setText(waterMarkName);
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
// 在内容上方加水印,不要在下方加水印,部分文档存在背景图片,会加不上的
under = stamper.getOverContent(i);
under.saveState();
under.setGState(gs);
under.beginText();
under.setFontAndSize(base, fontAndSize);
under.setColorFill(baseColor);
// 水印文字成30度角倾斜
for (int height = interval + textH; height < pageRect.getHeight();
height = height + textH * 3) {
for (int width = interval + textW; width < pageRect.getWidth() + textW;
width = width + textW * 2) {
under.showTextAligned(Element.ALIGN_LEFT
, waterMarkName, width - textW,
height - textH, 30);
under.setGState(gs);
}
}
// 添加水印文字
under.endText();
}
stamper.close();
reader.close();
} catch (Exception e) {
logger.error("IntegrationFileUtil工具类文字水印添加异常"+ e.getMessage());
}
}
/**
* @author yuezejian
* <p>描述: 给PDF添加水印(文字+图片)
* <p>日期: 2023年2月24日 下午3:20:26
* @param inputFile 原文件路径+名称
* @param outputFile 添加水印后输出文件保存的路径+名称
* @param waterMarkName 添加水印的内容
* @param img 图片水印
* @param textH 文字水印区域高度
* @param textW 文字水印区域宽度
* @param fontAndSize 水印字体大小
* @param R red 色域 (0-255)
* @param G green 色域(0-255)
* @param B blue 色域(0-255)
* @param moveH 移动图片的高度 ,文字水印和图片水印的位置关系,通过此参数调节
* @param moveW 移动图片的宽度,文字水印和图片水印的位置关系,通过此参数调节
*/
public static void PDFAddWatermarkAndPicture(String inputFile,String outputFile, String waterMarkName, Image img, int textH, int textW, int fontAndSize, int R,int G, int B, float textFillOpacity, float imageFillOpacity, int moveH, int moveW) {
try {
// 参数默认赋值
if (textH == 0) {
textH = 45;
}
if (textW == 0) {
textW = 100;
}
if (fontAndSize == 0) {
fontAndSize = 15;
}
if (R == 0) {
R = 2;
}
if (G == 0) {
G = 152;
}
if (B == 0) {
G = 246;
}
// 间隔距离(参数可调节)
int interval = 30;
// 切记这里的参数是文件的路径 ,路径必须是双斜杠的如F:\\test.pdf,不能是F:/test.pdf 或者F:\test.pdf
PdfReader reader = new PdfReader(inputFile);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
// 设置文字水印样式
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
// 设置字体颜色
BaseColor baseColor = new BaseColor(R,G,B);
PdfGState gs = new PdfGState();
gs.setFillOpacity(textFillOpacity);//改透明度
gs.setStrokeOpacity(0.4f);
int total = reader.getNumberOfPages() + 1;
JLabel label = new JLabel();
label.setText(waterMarkName);
PdfContentByte under;
// 可添加多个文字水印
Rectangle pageRect = null;
label.setText(waterMarkName);
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
// 在内容上方加水印
under = stamper.getOverContent(i);
under.saveState();
under.setGState(gs);
under.beginText();
under.setFontAndSize(base, fontAndSize);
under.setColorFill(baseColor);
// 水印文字成30度角倾斜
for (int height = interval + textH; height < pageRect.getHeight();
height = height + textH * 3) {
for (int width = interval + textW; width < pageRect.getWidth() + textW;
width = width + textW * 2) {
under.showTextAligned(Element.ALIGN_LEFT
, waterMarkName, width - textW,
height - textH, 30);
under.setGState(gs);
}
}
// 添加水印文字
under.endText();
}
gs.setFillOpacity(imageFillOpacity);//改透明度
if (null != img) {
// 设置图片水印
PdfContentByte over;
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
for (int height = interval + textH; height < pageRect.getHeight();
height = height + textH * 3) {
for (int width = interval + textW; width < pageRect.getWidth() + textW;
width = width + textW * 2) {
over = stamper.getOverContent(i);
over.setGState(gs);
img.setAbsolutePosition(width - textW + moveW,height - textH + moveH);
img.setRotationDegrees(30);
img.setAlignment(Element.ALIGN_LEFT);
over.addImage(img);
}
}
}
}
stamper.close();
reader.close();
} catch (Exception e) {
logger.error("IntegrationFileUtil工具类给PDF添加水印(文字加图片)异常"+ e.getMessage());
}
}
/**
* @author yuezejian
* <p>描述: 可编辑类型pdf转图片类型pdf
* <p>日期: 2023年2月24日 下午3:20:26
* @param inputFile 可编辑的pdf文件
* @param outputFile 图片型pdf文件
* @throws IOException
*/
public static void ImagesToOnePdf(String inputFile, String outputFile) throws IOException {
// 将inputStream文件流转成pdf文档里
PDDocument docfile = PDDocument.load(new File(inputFile));
// PDFRenderer将pdf转化成图片
PDFRenderer renderer = new PDFRenderer(docfile);
// 图片合成后的pdf文档类
PDDocument doc = new PDDocument();
PDPage page;
PDImageXObject pdImage;
PDPageContentStream contents;
float w, h;
int pageCount = docfile.getNumberOfPages();
for (int i = 0; i < pageCount; i++) {
// 144 高清图片 72 放大时模糊
BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
pdImage = LosslessFactory.createFromImage(doc, image);
w = 510;
h = 680;
page = new PDPage(new PDRectangle(w, h));
contents = new PDPageContentStream(doc, page);
contents.drawImage(pdImage, 0, 0, w, h);
contents.close();
doc.addPage(page);
}
//保存pdf
doc.save(new FileOutputStream(outputFile));
//关闭pdf
doc.close();
}
public static void main(String[] args) throws DocumentException, IOException {
int a = 1;
String pdffilepath = "C:\\Users\\Administrator\\Desktop\\测试文件\\123.pdf"; // 需要加水印的pdf文件
String pdfmarkfilepath = "C:\\Users\\Administrator\\Desktop\\测试文件\\template"+a+".pdf"; // 加完水印后,生成的可编辑pdf文件
String pdfmarkfilepath2 = "C:\\Users\\Administrator\\Desktop\\测试文件\\result"+a+".pdf"; // 转换后的图片型pdf文件
String watermarkurl = "C:\\Users\\Administrator\\Desktop\\测试文件\\bb.png"; // 水印图片,自行找公司的设计小姐姐要就行,她知道给你什么格式
try {
// 水印的倾斜角度一般都是30度,如有特殊需求,可自行修改倾角参数
// PDFAddWatermark(pdffilepath, pdfmarkfilepath, "DBKJ-咖啡汪出品-20230320", 45,100,15, 2, 152, 246);
PDFAddWatermarkAndPicture(pdffilepath, pdfmarkfilepath, "咖啡汪出品-20230320", Image.getInstance(watermarkurl),45,100,15, 2, 152, 246, 0.8f, 0.8f,70, 115);
ImagesToOnePdf(pdfmarkfilepath, pdfmarkfilepath2);
// 如碰到问题无法解决,可在评论区留意,大家可以一起探讨。
} catch (Exception e) {}
}
}
本文参考:
https://blog.csdn.net/weixin_44760690/article/details/121997820 java实现给PDF文件添加图片水印,java实现给PDF文件添加文字水印
https://blog.csdn.net/yyhlichao/article/details/84304966 itextpdf生成pdf中文乱码 (乱码中挣扎的自述)