1.maven依赖
org.apache.poi
poi
3.16
org.apache.poi
poi-ooxml
3.16
com.itextpdf
itext-asian
5.2.0
org.apache.pdfbox
pdfbox
2.0.18
com.itextpdf
itextpdf
5.5.13.1
org.springframework
spring-mock
2.0.8
2.工具类
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.*;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import org.apache.poi.hslf.usermodel.HSLFPictureShape;
import org.apache.poi.hslf.usermodel.HSLFSlide;
import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.stream.Stream;
/**
* @author: dumin3
* @date: 2020/9/9 15:22
* @description:
*/
public class WaterMarkUtils {
// word字体
private static final String fontName = "宋体";
// 字体大小
private static final String fontSize = "0.2pt";
// 字体颜色
private static final String fontColor = "#d0d0d0";
// 一个字平均长度,单位pt,用于:计算文本占用的长度(文本总个数*单字长度)
private static final Integer widthPerWord = 10;
// 与顶部的间距
private static Integer styleTop = 0;
// 文本旋转角度
private static final String styleRotation = "45";
/**
* @param file:
* @param markText:
* @param type:
* @return: org.springframework.web.multipart.MultipartFile
* @author: dumin3
* @date: 2020/9/9 16:48
* @description: word文档类型判断后添加水印
*/
public static MultipartFile setWordWaterMark(MultipartFile file,String markText,String type){
if (type.equals("docx")){
try {
XWPFDocument doc = new XWPFDocument(file.getInputStream());
waterMarkDocXDocument(doc,markText);
ByteArrayOutputStream baos = new ByteArrayOutputStream();//二进制OutputStream
doc.write(baos);//文档写入流
ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());//OutputStream写入InputStream二进制流
MultipartFile multipartFile = new MockMultipartFile(file.getName(),file.getOriginalFilename(),"", in);
return multipartFile;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else if (type.equals("doc")){
try {
HWPFDocument doc1 = new HWPFDocument(file.getInputStream());
Range range = doc1.getRange();
return file;
/* OfficeDrawings officeDrawing = doc1.getOfficeDrawingsMain();
officeDrawing.
XWPFDocument doc = new XWPFDocument(file.getInputStream());
waterMarkDocXDocument(doc,markText);
ByteArrayOutputStream baos = new ByteArrayOutputStream();//二进制OutputStream
doc.write(baos);//文档写入流
ByteArrayInputStream in = new ByteArrayInputStream(baos.toByteArray());//OutputStream写入InputStream二进制流
MultipartFile multipartFile = new MockMultipartFile(file.getName(),file.getOriginalFilename(),"", in);
return multipartFile;*/
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else if (type.equals("jpg")||type.equals("jpeg")||type.equals("png")){
return markImageByText(file,markText,45);
} else if (type.equals("xlsx")||type.equals("xls")) {
return setExcelWaterMark(file, markText,type);
} else if (type.equals("pptx")||type.equals("ppt")){
return setPPTWaterMark(file,markText,type);
} else if (type.equals("pdf")){
return setPDFWatermark(file,markText);
}
return file;
}
/**********************************---------------------docx添加水印----------------------**********************************/
/**
* 给文档添加水印
* 此方法可以单独使用
* @param doc
* @param customText
*/
public static void waterMarkDocXDocument(XWPFDocument doc,String customText){
// 把整页都打上水印
for (int lineIndex = -5; lineIndex < 20; lineIndex++) {
styleTop = 100*lineIndex;
waterMarkDocXDocument_0(doc,customText);
}
}
/**
* 为文档添加水印
* @param doc 需要被处理的docx文档对象
* @param customText 需要添加的水印文字
*/
public static void waterMarkDocXDocument_0(XWPFDocument doc,String customText) {
// 水印文字之间使用8个空格分隔
customText = customText + repeatString(" ", 8);
// 一行水印重复水印文字次数
customText = repeatString(customText, 10);
// 如果之前已经创建过 DEFAULT 的Header,将会复用
XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT);
int size = header.getParagraphs().size();
if (size == 0) {
header.createParagraph();
}
CTP ctp = header.getParagraphArray(0).getCTP();
byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
ctp.setRsidP(rsidr);
ctp.setRsidRDefault(rsidrdefault);
CTPPr ppr = ctp.addNewPPr();
ppr.addNewPStyle().setVal("Header");
// 开始加水印
CTR ctr = ctp.addNewR();
CTRPr ctrpr = ctr.addNewRPr();
ctrpr.addNewNoProof();
CTGroup group = CTGroup.Factory.newInstance();
CTShapetype shapetype = group.addNewShapetype();
CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
shapeTypeTextPath.setOn(STTrueFalse.T);
shapeTypeTextPath.setFitshape(STTrueFalse.T);
CTLock lock = shapetype.addNewLock();
lock.setExt(STExt.VIEW);
CTShape shape = group.addNewShape();
shape.setId("PowerPlusWaterMarkObject");
shape.setSpid("_x0000_s102");
shape.setType("#_x0000_t136");
// 设置形状样式(旋转,位置,相对路径等参数)
shape.setStyle(getShapeStyle(customText));
shape.setFillcolor(fontColor);
// 字体设置为实心
shape.setStroked(STTrueFalse.FALSE);
// 绘制文本的路径
CTTextPath shapeTextPath = shape.addNewTextpath();
// 设置文本字体与大小
shapeTextPath.setStyle("font-family:" + fontName + ";font-size:" + fontSize);
shapeTextPath.setString(customText);
CTPicture pict = ctr.addNewPict();
pict.set(group);
}
/**
* 构建Shape的样式参数
* @param customText
* @return
*/
private static String getShapeStyle(String customText) {
StringBuilder sb = new StringBuilder();
// 文本path绘制的定位方式
sb.append("position: ").append("absolute");
// 计算文本占用的长度(文本总个数*单字长度)
sb.append(";width: ").append(customText.length() * widthPerWord).append("pt");
// 字体高度
sb.append(";height: ").append("20pt");
sb.append(";z-index: ").append("-251654144");
sb.append(";mso-wrap-edited: ").append("f");
// 设置水印的间隔,这是一个大坑,不能用top,必须要margin-top。
sb.append(";margin-top: ").append(styleTop);
sb.append(";mso-position-horizontal-relative: ").append("page");
sb.append(";mso-position-vertical-relative: ").append("page");
sb.append(";mso-position-vertical: ").append("left");
sb.append(";mso-position-horizontal: ").append("center");
sb.append(";rotation: ").append(styleRotation);
return sb.toString();
}
/**
* 将指定的字符串重复repeats次.
*/
private static String repeatString(String pattern, int repeats) {
StringBuilder buffer = new StringBuilder(pattern.length() * repeats);
Stream.generate(() -> pattern).limit(repeats).forEach(buffer::append);
return new String(buffer);
}
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**********************************---------------------图片添加水印----------------------**********************************/
// 水印透明度
private static float alpha = 0.5f;
// 水印横向位置
private static int positionWidth = 0;
// 水印纵向位置
private static int positionHeight = 300;
// 水印文字字体
private static Font font = new Font("宋体", Font.BOLD, 32);
// 水印文字颜色
private static Color color = Color.gray;
/**
*
* @param alpha
* 水印透明度
* @param positionWidth
* 水印横向位置
* @param positionHeight
* 水印纵向位置
* @param font
* 水印文字字体
* @param color
* 水印文字颜色
*/
public static void setImageMarkOptions(float alpha, int positionWidth,
int positionHeight, Font font, Color color) {
if (alpha != 0.0f)
WaterMarkUtils.alpha = alpha;
if (positionWidth != 0)
WaterMarkUtils.positionWidth = positionWidth;
if (positionHeight != 0)
WaterMarkUtils.positionHeight = positionHeight;
if (font != null)
WaterMarkUtils.font = font;
if (color != null)
WaterMarkUtils.color = color;
}
/**
* 给图片添加水印文字、可设置水印文字的旋转角度
*
* @param logoText
* @param multipartFile
* @param degree
*/
public static MultipartFile markImageByText(MultipartFile multipartFile, String logoText,Integer degree) {
InputStream is = null;
OutputStream os = null;
try {
// 1、源图片
JPEGImageDecoder decoderFile = JPEGCodec.createJPEGDecoder(multipartFile.getInputStream());
BufferedImage buffImg = decoderFile.decodeAsBufferedImage();
//Image可以获得 输入图片的信息
int width = buffImg.getWidth(null);
int height = buffImg.getHeight(null);
// 2、得到画笔对象
Graphics2D g = buffImg.createGraphics();
// 3、设置对线段的锯齿状边缘处理
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(
buffImg.getScaledInstance(buffImg.getWidth(null),
buffImg.getHeight(null), buffImg.SCALE_SMOOTH), 0, 0,
null);
// 4、设置水印旋转
if (null != degree) {
g.rotate(Math.toRadians(degree),
(double) buffImg.getWidth() / 2,
(double) buffImg.getHeight() / 2);
}
// 5、设置水印文字颜色
g.setColor(color);
// 6、设置水印文字Font
g.setFont(font);
// 7、设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
alpha));
// 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
for(int i=0;i<9;i++){
for(int j = 0;j<6;j++){
g.drawString(logoText, (int) (width - (width*j/3)), (int) (height - (height*i/5)));
}
}
// 9、释放资源
g.dispose();
// 10、生成图片
InputStream in = bufferedImageToInputStream(buffImg);
MultipartFile file = new MockMultipartFile(multipartFile.getName(),multipartFile.getOriginalFilename(),"", in);
System.out.println("图片完成添加水印文字");
return file;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != is)
is.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (null != os)
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**********************************---------------------Excel添加水印----------------------**********************************/
/**
* 将BufferedImage转换为InputStream
* @param image
* @return
*/
public static InputStream bufferedImageToInputStream(BufferedImage image){
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(image, "png", os);
InputStream input = new ByteArrayInputStream(os.toByteArray());
return input;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 为Excel打上水印工具函数 请自行确保参数值,以保证水印图片之间不会覆盖。 在计算水印的位置的时候,并没有考虑到单元格合并的情况,请注意
*
* @param wb
* Excel Workbook
* @param sheet
* 需要打水印的Excel
* @param bufferImg
* 水印地址,classPath,目前只支持png格式的图片,
* 因为非png格式的图片打到Excel上后可能会有图片变红的问题,且不容易做出透明效果。
* 同时请注意传入的地址格式,应该为类似:"\\excelTemplate\\test.png"
* @param startXCol
* 水印起始列
* @param startYRow
* 水印起始行
* @param betweenXCol
* 水印横向之间间隔多少列
* @param betweenYRow
* 水印纵向之间间隔多少行
* @param XCount
* 横向共有水印多少个
* @param YCount
* 纵向共有水印多少个
* @param waterRemarkWidth
* 水印图片宽度为多少列
* @param waterRemarkHeight
* 水印图片高度为多少行
* @throws IOException
*/
public static void putWaterRemarkToExcel(Workbook wb, Sheet sheet,BufferedImage bufferImg, int startXCol,
int startYRow, int betweenXCol, int betweenYRow, int XCount, int YCount, int waterRemarkWidth,
int waterRemarkHeight) throws IOException {
// 导出到字节流B
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferImg, "png", os);
// 加载图片
// 开始打水印
Drawing drawing = sheet.createDrawingPatriarch();
// 按照共需打印多少行水印进行循环
for (int yCount = 0; yCount < YCount; yCount++) {
// 按照每行需要打印多少个水印进行循环
for (int xCount = 0; xCount < XCount; xCount++) {
// 创建水印图片位置
int xIndexInteger = startXCol + (xCount * waterRemarkWidth) + (xCount * betweenXCol);
int yIndexInteger = startYRow + (yCount * waterRemarkHeight) + (yCount * betweenYRow);
/*
* 参数定义: 第一个参数是(x轴的开始节点); 第二个参数是(是y轴的开始节点); 第三个参数是(是x轴的结束节点);
* 第四个参数是(是y轴的结束节点); 第五个参数是(是从Excel的第几列开始插入图片,从0开始计数);
* 第六个参数是(是从excel的第几行开始插入图片,从0开始计数); 第七个参数是(图片宽度,共多少列);
* 第8个参数是(图片高度,共多少行);
*/
ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, xIndexInteger,
yIndexInteger, xIndexInteger + waterRemarkWidth, yIndexInteger + waterRemarkHeight);
Picture pic = drawing.createPicture(anchor,
wb.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG));
pic.resize();
}
}
}
/**
* excel设置水印
* @param file
* @param markStr
*/
public static MultipartFile setExcelWaterMark(MultipartFile file, String markStr,String type){
try {
FontImage.Watermark watermark = new FontImage.Watermark();
watermark.setText("水印测试");
BufferedImage image = FontImage.createWatermarkImage(null);
if (type.equals("xlsx")) {
XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
//获取excel sheet个数
int sheets = workbook.getNumberOfSheets();
//循环sheet给每个sheet添加水印
for (int i = 0; i < sheets; i++) {
XSSFSheet sheet = workbook.getSheetAt(i);
// 导出到字节流B
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(image, "png", os);
int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
//add relation from sheet to the picture data
String rID = sheet.addRelation(null, XSSFRelation.IMAGES, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();
//set background picture to sheet
sheet.getCTWorksheet().addNewPicture().setId(rID);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
workbook.write(bos);
byte[] barray = bos.toByteArray();
InputStream is = new ByteArrayInputStream(barray);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getOriginalFilename(), "", is);
return multipartFile;
} else {
HSSFWorkbook wb = new HSSFWorkbook(file.getInputStream());
//获取excel sheet个数
int sheets = wb.getNumberOfSheets();
//循环sheet给每个sheet添加水印
for (int i = 0; i < sheets; i++) {
Sheet sheet = wb.getSheetAt(i);
putWaterRemarkToExcel(wb, sheet, image, 0, 0, 6, 10, 10, 10, 0, 0);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
wb.write(bos);
byte[] barray = bos.toByteArray();
InputStream is = new ByteArrayInputStream(barray);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getOriginalFilename(), "", is);
return multipartFile;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**********************************---------------------PPT添加水印----------------------**********************************/
/**
* @param file:
* @param markStr:
* @param fileType:
* @return: void
* @author: dumin3
* @date: 2020/9/10 13:35
* @description: ppt 添加水印
*/
public static MultipartFile setPPTWaterMark(MultipartFile file, String markStr, String fileType) {
try {
//设置水印图片
FontImage.Watermark watermark = new FontImage.Watermark();
watermark.setText("水印测试");
BufferedImage image = FontImage.createWatermarkImage(null);
if ("pptx".equals(fileType)) {
XMLSlideShow slideShow = new XMLSlideShow(file.getInputStream());
byte[] pictureData = imageToBytes(image);
PictureData pictureData1 = slideShow.addPicture(pictureData, PictureData.PictureType.PNG);
for (XSLFSlide slide : slideShow.getSlides()) {
for(int i =0 ; i<10;i++) {
for(int j = 0;j<8;j++) {
XSLFPictureShape pictureShape = slide.createPicture(pictureData1);
pictureShape.setAnchor(new java.awt.Rectangle(200 * i, 80 * j, 150, 50));
}
}
CTSlide ctSlide = slide.getXmlObject();
XmlObject[] allText = ctSlide.selectPath(
"declare namespace a='http://schemas.openxmlformats.org/drawingml/2006/main' " +
".//a:t"
);
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
slideShow.write(bos);
slideShow.close();
bos.close();
byte[] barray = bos.toByteArray();
InputStream is = new ByteArrayInputStream(barray);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getOriginalFilename(), "", is);
return multipartFile;
} else if ("ppt".equals(fileType)) {
HSLFSlideShow ppt = new HSLFSlideShow(file.getInputStream());
byte[] pictureByte = imageToBytes(image);
PictureData pictureData1 = ppt.addPicture(pictureByte, PictureData.PictureType.PNG);
for (HSLFSlide slide : ppt.getSlides()) {
for(int i =0 ; i<10;i++) {
for(int j = 0;j<7;j++) {
HSLFPictureShape pictureShape = slide.createPicture(pictureData1);
pictureShape.setAnchor(new java.awt.Rectangle(200 * i, 80 * j, 150, 50));
}
}
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ppt.write(bos);
ppt.close();
bos.close();
byte[] barray = bos.toByteArray();
InputStream is = new ByteArrayInputStream(barray);
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getOriginalFilename(), "", is);
return multipartFile;
}
} catch (IOException e){
e.printStackTrace();
}
return null;
}
/**
* BufferedImage转byte[]
*
* @param bImage BufferedImage对象
* @return byte[]
* @auth zhy
*/
private static byte[] imageToBytes(BufferedImage bImage) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
ImageIO.write(bImage, "png", out);
} catch (IOException e) {
}
return out.toByteArray();
}
/**********************************---------------------PDF添加水印----------------------**********************************/
/**
*
* @param file
* 原PDF文件
* @param waterMarkName
* 页脚添加水印
* @throws DocumentException
* @throws IOException
*/
public static MultipartFile setPDFWatermark(MultipartFile file,String waterMarkName) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfReader reader = new PdfReader(file.getInputStream());
PdfStamper stamper = new PdfStamper(reader, bos);
// 获取总页数 +1, 下面从1开始遍历
int total = reader.getNumberOfPages() + 1;
// 使用classpath下面的字体库
BaseFont base = null;
try {
base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
} catch (Exception e) {
// 日志处理
e.printStackTrace();
}
// 间隔
int interval = -5;
// 获取水印文字的高度和宽度
int textH = 0, textW = 0;
JLabel label = new JLabel();
label.setText(waterMarkName);
FontMetrics metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
System.out.println("textH: " + textH);
System.out.println("textW: " + textW);
// 设置水印透明度
PdfGState gs = new PdfGState();
gs.setFillOpacity(0.2f);
gs.setStrokeOpacity(0.2f);
com.itextpdf.text.Rectangle pageSizeWithRotation = null;
PdfContentByte content = null;
for (int i = 1; i < total; i++) {
// 在内容上方加水印
content = stamper.getOverContent(i);
// 在内容下方加水印
// content = stamper.getUnderContent(i);
content.saveState();
content.setGState(gs);
// 设置字体和字体大小
content.beginText();
content.setFontAndSize(base, 20);
// 获取每一页的高度、宽度
pageSizeWithRotation = reader.getPageSizeWithRotation(i);
float pageHeight = pageSizeWithRotation.getHeight();
float pageWidth = pageSizeWithRotation.getWidth();
// 根据纸张大小多次添加, 水印文字成30度角倾斜
for (int height = interval + textH; height < pageHeight; height = height + textH * 3) {
for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {
content.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, 30);
}
}
content.endText();
}
// 关流
stamper.close();
reader.close();
bos.close();
InputStream is = new ByteArrayInputStream(bos.toByteArray());
MultipartFile multipartFile = new MockMultipartFile(file.getName(), file.getOriginalFilename(), "", is);
return multipartFile;
} catch (DocumentException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
return null;
}
}
package com.fehorizon.hmwf.integration.common.utils;
import com.alibaba.druid.util.StringUtils;
import lombok.Data;
import java.awt.*;
import java.awt.image.BufferedImage;
/**
* @author: dumin3
* @date: 2020/9/10 11:03
* @description:根据文字生成水印图片
*/
public class FontImage {
@Data
public static class Watermark {
private Boolean enable;
private String text;
private String dateFormat;
private String color;
}
public static BufferedImage createWatermarkImage(Watermark watermark) {
if (watermark == null) {
watermark = new FontImage.Watermark();
watermark.setEnable(true);
// watermark.setText("userName");
watermark.setText("水印测试");
watermark.setColor("#C5CBCF");
watermark.setDateFormat("yyyy-MM-dd HH:mm");
} else {
if (StringUtils.isEmpty(watermark.getDateFormat())) {
watermark.setDateFormat("yyyy-MM-dd HH:mm");
} else if (watermark.getDateFormat().length() == 16) {
watermark.setDateFormat("yyyy-MM-dd HH:mm");
} else if (watermark.getDateFormat().length() == 10) {
watermark.setDateFormat("yyyy-MM-dd");
}
if (StringUtils.isEmpty(watermark.getText())) {
watermark.setText("水印测试");
}
if (StringUtils.isEmpty(watermark.getColor())) {
watermark.setColor("#C5CBCF");
}
}
String[] textArray = watermark.getText().split("\n");
Font font = new Font("microsoft-yahei", Font.PLAIN, 50);
Integer width = 200;
Integer height = 200;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 背景透明 开始
Graphics2D g = image.createGraphics();
image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
g.dispose();
// 背景透明 结束
g = image.createGraphics();
g.setColor(new Color(Integer.parseInt(watermark.getColor().substring(1), 16)));// 设定画笔颜色
g.setFont(font);// 设置画笔字体
g.shear(0.1, 0.5);// 设定倾斜度
// 设置字体平滑
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int y = 50;
y = y + font.getSize();
// for (int i = 0; i < textArray.length; i++) {
// g.drawString(textArray[i], 0, y);// 画出字符串
// y = y + font.getSize();
// }
g.drawString(watermark.getText(), 0, y);// 画出字符串
g.dispose();// 释放画笔
return image;
}
}