java实现加水印功能

news/2024/12/21 20:08:08/

1-Word加水印

在这里插入图片描述
在这里插入图片描述
实现原理:
● 通过页眉页脚生成文字水印或图片水印,然后设置页眉页脚的高度以及旋转角度来设置水印。

源代码:
1、引入pom依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.14</version>
</dependency><dependency><groupId>com.luhuiguo</groupId><artifactId>aspose-words</artifactId><version>22.4</version><type>pom</type>
</dependency>

2、重写apache中的XWPFHeaderFooterPolicy类。
● 注意:包名为org.apache.poi.xwpf.model

java">package org.apache.poi.xwpf.model;
/*** Created at 2023年9月10日* Created by Alexander*/import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.office.office.STConnectType;
import com.microsoft.schemas.vml.*;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLDocumentPart.RelationPart;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.HdrDocument.Factory;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STHdrFtr.Enum;import java.util.Iterator;
import java.util.Map;/*** <p>Author: Alexander的搬砖工地</p>* <p>Date: 2023年9月15日</p>*/
public class XWPFHeaderFooterPolicy {public static final Enum DEFAULT;public static final Enum EVEN;public static final Enum FIRST;private XWPFDocument doc;private XWPFHeader firstPageHeader;private XWPFFooter firstPageFooter;private XWPFHeader evenPageHeader;private XWPFFooter evenPageFooter;private XWPFHeader defaultHeader;private XWPFFooter defaultFooter;public XWPFHeaderFooterPolicy(XWPFDocument doc) {this(doc, (CTSectPr) null);}public XWPFHeaderFooterPolicy(XWPFDocument doc, CTSectPr sectPr) {if (sectPr == null) {CTBody i = doc.getDocument().getBody();sectPr = i.isSetSectPr() ? i.getSectPr() : i.addNewSectPr();}this.doc = doc;CTHdrFtrRef ref;org.apache.poi.POIXMLDocumentPart relatedPart;Enum type;int var11;for (var11 = 0; var11 < sectPr.sizeOfHeaderReferenceArray(); ++var11) {ref = sectPr.getHeaderReferenceArray(var11);relatedPart = doc.getRelationById(ref.getId());XWPFHeader ftr = null;if (relatedPart != null && relatedPart instanceof XWPFHeader) {ftr = (XWPFHeader) relatedPart;}try {type = ref.getType();} catch (XmlValueOutOfRangeException var10) {type = STHdrFtr.DEFAULT;}this.assignHeader(ftr, type);}for (var11 = 0; var11 < sectPr.sizeOfFooterReferenceArray(); ++var11) {ref = sectPr.getFooterReferenceArray(var11);relatedPart = doc.getRelationById(ref.getId());XWPFFooter var12 = null;if (relatedPart != null && relatedPart instanceof XWPFFooter) {var12 = (XWPFFooter) relatedPart;}try {type = ref.getType();} catch (XmlValueOutOfRangeException var9) {type = STHdrFtr.DEFAULT;}this.assignFooter(var12, type);}}private void assignFooter(XWPFFooter ftr, Enum type) {if (type == STHdrFtr.FIRST) {this.firstPageFooter = ftr;} else if (type == STHdrFtr.EVEN) {this.evenPageFooter = ftr;} else {this.defaultFooter = ftr;}}private void assignHeader(XWPFHeader hdr, Enum type) {if (type == STHdrFtr.FIRST) {this.firstPageHeader = hdr;} else if (type == STHdrFtr.EVEN) {this.evenPageHeader = hdr;} else {this.defaultHeader = hdr;}}public XWPFHeader createHeader(Enum type) {return this.createHeader(type, (XWPFParagraph[]) null);}public XWPFHeader createHeader(Enum type, XWPFParagraph[] pars) {XWPFHeader header = this.getHeader(type);//存在hdader则覆盖//	        if(header == null) {HdrDocument hdrDoc = Factory.newInstance();XWPFRelation relation = XWPFRelation.HEADER;int i = this.getRelationIndex(relation);XWPFHeader wrapper = (XWPFHeader) this.doc.createRelationship(relation, XWPFFactory.getInstance(), i);wrapper.setXWPFDocument(this.doc);CTHdrFtr hdr = this.buildHdr(type, wrapper, pars);wrapper.setHeaderFooter(hdr);hdrDoc.setHdr(hdr);this.assignHeader(wrapper, type);header = wrapper;//	        }return header;}public XWPFFooter createFooter(Enum type) {return this.createFooter(type, (XWPFParagraph[]) null);}public XWPFFooter createFooter(Enum type, XWPFParagraph[] pars) {XWPFFooter footer = this.getFooter(type);//	        if (footer == null) {FtrDocument ftrDoc = (FtrDocument) FtrDocument.Factory.newInstance();XWPFRelation relation = XWPFRelation.FOOTER;int i = this.getRelationIndex(relation);XWPFFooter wrapper = (XWPFFooter) this.doc.createRelationship(relation, XWPFFactory.getInstance(), i);wrapper.setXWPFDocument(this.doc);CTHdrFtr ftr = this.buildFtr(type, wrapper, pars);wrapper.setHeaderFooter(ftr);ftrDoc.setFtr(ftr);this.assignFooter(wrapper, type);footer = wrapper;//	        }return footer;}private int getRelationIndex(XWPFRelation relation) {int i = 1;Iterator var3 = this.doc.getRelationParts().iterator();while (var3.hasNext()) {RelationPart rp = (RelationPart) var3.next();if (rp.getRelationship().getRelationshipType().equals(relation.getRelation())) {++i;}}return i;}private CTHdrFtr buildFtr(Enum type, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {CTHdrFtr ftr = this.buildHdrFtr(pars, wrapper);this.setFooterReference(type, wrapper);return ftr;}private CTHdrFtr buildHdr(Enum type, XWPFHeaderFooter wrapper, XWPFParagraph[] pars) {CTHdrFtr hdr = this.buildHdrFtr(pars, wrapper);this.setHeaderReference(type, wrapper);return hdr;}private CTHdrFtr buildHdrFtr(XWPFParagraph[] paragraphs, XWPFHeaderFooter wrapper) {CTHdrFtr ftr = wrapper._getHdrFtr();if (paragraphs != null) {for (int i = 0; i < paragraphs.length; ++i) {ftr.addNewP();ftr.setPArray(i, paragraphs[i].getCTP());}}return ftr;}private void setFooterReference(Enum type, XWPFHeaderFooter wrapper) {CTHdrFtrRef ref = this.doc.getDocument().getBody().getSectPr().addNewFooterReference();ref.setType(type);ref.setId(this.doc.getRelationId(wrapper));}private void setHeaderReference(Enum type, XWPFHeaderFooter wrapper) {CTHdrFtrRef ref = this.doc.getDocument().getBody().isSetSectPr() ? this.doc.getDocument().getBody().getSectPr().addNewHeaderReference() : this.doc.getDocument().getBody().addNewSectPr().addNewHeaderReference();ref.setType(type);ref.setId(this.doc.getRelationId(wrapper));}public XWPFHeader getFirstPageHeader() {return this.firstPageHeader;}public XWPFFooter getFirstPageFooter() {return this.firstPageFooter;}public XWPFHeader getOddPageHeader() {return this.defaultHeader;}public XWPFFooter getOddPageFooter() {return this.defaultFooter;}public XWPFHeader getEvenPageHeader() {return this.evenPageHeader;}public XWPFFooter getEvenPageFooter() {return this.evenPageFooter;}public XWPFHeader getDefaultHeader() {return this.defaultHeader;}public XWPFFooter getDefaultFooter() {return this.defaultFooter;}public XWPFHeader getHeader(int pageNumber) {return pageNumber == 1 && this.firstPageHeader != null ? this.firstPageHeader : (pageNumber % 2 == 0 && this.evenPageHeader != null ? this.evenPageHeader : this.defaultHeader);}public XWPFHeader getHeader(Enum type) {return type == STHdrFtr.EVEN ? this.evenPageHeader : (type == STHdrFtr.FIRST ? this.firstPageHeader : this.defaultHeader);}public XWPFFooter getFooter(int pageNumber) {return pageNumber == 1 && this.firstPageFooter != null ? this.firstPageFooter : (pageNumber % 2 == 0 && this.evenPageFooter != null ? this.evenPageFooter : this.defaultFooter);}public XWPFFooter getFooter(Enum type) {return type == STHdrFtr.EVEN ? this.evenPageFooter : (type == STHdrFtr.FIRST ? this.firstPageFooter : this.defaultFooter);}public void createWatermark(String text,Map<String,Object> params) {XWPFParagraph[] pars = new XWPFParagraph[]{this.getWatermarkParagraph(text, 1,params)};this.createHeader(DEFAULT, pars);pars[0] = this.getWatermarkParagraph(text, 2,params);this.createHeader(FIRST, pars);pars[0] = this.getWatermarkParagraph(text, 3,params);this.createHeader(EVEN, pars);}/*** 原方法备份* @param text* @param idx* @return*/private XWPFParagraph getWatermarkParagraph123(String text, int idx) {CTP p = (CTP) CTP.Factory.newInstance();byte[] rsidr = this.doc.getDocument().getBody().getPArray(0).getRsidR();byte[] rsidrdefault = this.doc.getDocument().getBody().getPArray(0).getRsidRDefault();p.setRsidP(rsidr);p.setRsidRDefault(rsidrdefault);CTPPr pPr = p.addNewPPr();pPr.addNewPStyle().setVal("Header");CTR r = p.addNewR();CTRPr rPr = r.addNewRPr();rPr.addNewNoProof();CTPicture pict = r.addNewPict();CTGroup group = (CTGroup) CTGroup.Factory.newInstance();CTShapetype shapetype = group.addNewShapetype();shapetype.setId("_x0000_t136");shapetype.setCoordsize("1600,21600");shapetype.setSpt(136.0F);shapetype.setAdj("10800");shapetype.setPath2("m@7,0l@8,0m@5,21600l@6,21600e");CTFormulas formulas = shapetype.addNewFormulas();formulas.addNewF().setEqn("sum #0 0 10800");formulas.addNewF().setEqn("prod #0 2 1");formulas.addNewF().setEqn("sum 21600 0 @1");formulas.addNewF().setEqn("sum 0 0 @2");formulas.addNewF().setEqn("sum 21600 0 @3");formulas.addNewF().setEqn("if @0 @3 0");formulas.addNewF().setEqn("if @0 21600 @1");formulas.addNewF().setEqn("if @0 0 @2");formulas.addNewF().setEqn("if @0 @4 21600");formulas.addNewF().setEqn("mid @5 @6");formulas.addNewF().setEqn("mid @8 @5");formulas.addNewF().setEqn("mid @7 @8");formulas.addNewF().setEqn("mid @6 @7");formulas.addNewF().setEqn("sum @6 0 @5");CTPath path = shapetype.addNewPath();path.setTextpathok(STTrueFalse.T);path.setConnecttype(STConnectType.CUSTOM);path.setConnectlocs("@9,0;@10,10800;@11,21600;@12,10800");path.setConnectangles("270,180,90,0");CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();shapeTypeTextPath.setOn(STTrueFalse.T);shapeTypeTextPath.setFitshape(STTrueFalse.T);CTHandles handles = shapetype.addNewHandles();CTH h = handles.addNewH();h.setPosition("#0,bottomRight");h.setXrange("6629,14971");CTLock lock = shapetype.addNewLock();lock.setExt(STExt.EDIT);CTShape shape = group.addNewShape();shape.setId("PowerPlusWaterMarkObject" + idx);shape.setSpid("_x0000_s102" + (4 + idx));shape.setType("#_x0000_t136");shape.setStyle("position:absolute;margin-left:0;margin-top:0;width:415pt;height:207.5pt;z-index:1;mso-wrap-edited:f;mso-position-horizontal:center;mso-position-horizontal-relative:margin;mso-position-vertical:center;mso-position-vertical-relative:margin");shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068");shape.setFillcolor("black");shape.setStroked(STTrueFalse.FALSE);CTTextPath shapeTextPath = shape.addNewTextpath();shapeTextPath.setStyle("font-family:&quot;Cambria&quot;;font-size:1pt");shapeTextPath.setString(text);pict.set(group);return new XWPFParagraph(p, this.doc);}/*** 重写方法* @param text* @param idx* @return*/private XWPFParagraph getWatermarkParagraph(String text, int idx,Map<String,Object> params) {CTP p = (CTP) CTP.Factory.newInstance();byte[] rsidr = this.doc.getDocument().getBody().getPArray(0).getRsidR();byte[] rsidrdefault = this.doc.getDocument().getBody().getPArray(0).getRsidRDefault();p.setRsidP(rsidr);p.setRsidRDefault(rsidrdefault);CTPPr pPr = p.addNewPPr();pPr.addNewPStyle().setVal("Header");CTR r = p.addNewR();if (idx == 1) {//margin-left和margin-top调整位置,height 和width调整大小setCTR(r, text, idx, "position:absolute;" +"left:0pt;" +"margin-left:35pt;" + // 左外边距"margin-top:200pt;" + // 上边距"mso-position-horizontal-relative:margin;" +"mso-position-vertical-relative:margin;" +"rotation:330.0" +//(360-30) +// 旋转角度";height:60pt;" + // 文字高度"width:360pt;" + // 文字宽度"mso-width-relative:page;" +"mso-height-relative:page",params);} else {setCTR(r, text, idx, "position:absolute;left:0pt;mso-position-horizontal-relative:margin;mso-position-vertical-relative:margin;rotation:-2949120f;height:60pt;width:360pt;mso-width-relative:page;mso-height-relative:page",params);}return new XWPFParagraph(p, this.doc);}/*** 添加水印* @param r* @param text* @param idx* @param style*/private void setCTR(CTR r, String text, int idx, String style, Map<String,Object> params) {CTRPr rPr = r.addNewRPr();rPr.addNewNoProof();CTPicture pict = r.addNewPict();CTGroup group = (CTGroup) CTGroup.Factory.newInstance();CTShapetype shapetype = group.addNewShapetype();shapetype.setId("_x0000_t136");shapetype.setCoordsize("1600,21600");shapetype.setSpt(136.0F);// 水印内容框shapetype.setAdj("10800");shapetype.setPath2("m@7,0l@8,0m@5,21600l@6,21600e");CTFormulas formulas = shapetype.addNewFormulas();formulas.addNewF().setEqn("sum #0 0 10800");formulas.addNewF().setEqn("prod #0 2 1");formulas.addNewF().setEqn("sum 21600 0 @1");formulas.addNewF().setEqn("sum 0 0 @2");formulas.addNewF().setEqn("sum 21600 0 @3");formulas.addNewF().setEqn("if @0 @3 0");formulas.addNewF().setEqn("if @0 21600 @1");formulas.addNewF().setEqn("if @0 0 @2");formulas.addNewF().setEqn("if @0 @4 21600");formulas.addNewF().setEqn("mid @5 @6");formulas.addNewF().setEqn("mid @8 @5");formulas.addNewF().setEqn("mid @7 @8");formulas.addNewF().setEqn("mid @6 @7");formulas.addNewF().setEqn("sum @6 0 @5");CTPath path = shapetype.addNewPath();path.setTextpathok(STTrueFalse.T);path.setConnecttype(STConnectType.CUSTOM);path.setConnectlocs("@9,0;@10,10800;@11,21600;@12,10800");path.setConnectangles("270,180,90,0");CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();shapeTypeTextPath.setOn(STTrueFalse.T);shapeTypeTextPath.setFitshape(STTrueFalse.T);CTHandles handles = shapetype.addNewHandles();CTH h = handles.addNewH();h.setPosition("#0,bottomRight");h.setXrange("6629,14971");CTLock lock = shapetype.addNewLock();lock.setExt(STExt.EDIT);CTShape shape = group.addNewShape();shape.setId("PowerPlusWaterMarkObject" + idx);shape.setSpid("_x0000_s102" + (4 + idx));shape.setType("#_x0000_t136");shape.setStyle(style);shape.setWrapcoords("616 5068 390 16297 39 16921 -39 17155 7265 17545 7186 17467 -39 17467 18904 17467 10507 17467 8710 17545 18904 17077 18787 16843 18358 16297 18279 12554 19178 12476 20701 11774 20779 11228 21131 10059 21248 8811 21248 7563 20975 6316 20935 5380 19490 5146 14022 5068 2616 5068");//添加水印颜色shape.setFillcolor("#CC00FF");// 透明度//        Double alpha1 = Double.parseDouble("0.5");//        String alpha = Double.toString(alpha1*100000);shape.setOpacity("50000");shape.setStroked(STTrueFalse.FALSE);CTTextPath shapeTextPath = shape.addNewTextpath();shapeTextPath.setStyle("font-family:&quot;Cambria&quot;;font-size:1pt");shapeTextPath.setString(text);pict.set(group);}static {DEFAULT = STHdrFtr.DEFAULT;EVEN = STHdrFtr.EVEN;FIRST = STHdrFtr.FIRST;}}

3、主类

java">public class WaterMarkUtils {private static String inputPath  = "F:/临时/测试2.docx";private static String inputPathToDocx  = "F:/临时/测试444.docx";private static String outPath  = "F:/临时/测试结果.docx";private static String markStr = "Garbage水印!";public static void main(String[] args) {Map<String, Object> params = new HashMap<>();String type = inputPath.substring((inputPath.lastIndexOf(".") + 1));if ("doc".equals(type)) {docToDocx(inputPath,inputPathToDocx);setWordWaterMark(inputPathToDocx,outPath,markStr,params);} else if ("docx".equals(type)) {setWordWaterMark(inputPath, outPath, markStr,params);} else {System.out.println("格式有误!");}}/*** doc文档转docx* @param inPath doc原文件路径* @param outPath 转为docx的路径*/public static void docToDocx(String inPath, String outPath) {try {File file = new File(outPath);FileOutputStream os = new FileOutputStream(file);Document doc = new Document(inPath);doc.save(os, SaveFormat.DOCX);// 这里可以写你想要装换的类型:DOC, DOCX, PDF,HTML} catch (Exception e) {e.printStackTrace();}}/*** 设置水印* @param inputPath 输入的docx路径* @param outPath 文件保存路径* @param markStr 水印内容* @param params 其他参数(预留传入其他参数,如透明度、颜色等等)*/public static void setWordWaterMark(String inputPath, String outPath, String markStr, Map<String,Object> params) {File inputFile = new File(inputPath);XWPFDocument doc = null;try {// 延迟解析比率ZipSecureFile.setMinInflateRatio(-1.0d);doc = new XWPFDocument(new FileInputStream(inputFile));} catch (FileNotFoundException e) {System.out.println( "源文件不存在");e.printStackTrace();} catch (IOException e) {System.out.println( "读取源文件IO异常");e.printStackTrace();} catch (Exception e) {System.out.println( "不支持的文档格式");e.printStackTrace();}org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();if (headerFooterPolicy == null) {headerFooterPolicy = doc.createHeaderFooterPolicy();}//添加水印headerFooterPolicy.createWatermark(markStr,params);File file = new File(outPath);if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {System.out.println( "创建输出文件失败");e.printStackTrace();}}OutputStream os = null;try {os = new FileOutputStream(outPath);doc.write(os);} catch (FileNotFoundException e) {System.out.println( "创建输出文件失败");e.printStackTrace();} catch (Exception e) {System.out.println( "添加文档水印失败");e.printStackTrace();} finally {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}if (doc != null) {try {doc.close();} catch (IOException e) {e.printStackTrace();}}}}
}

2-PPT加水印

在这里插入图片描述
1、导入依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>4.1.2</version>
</dependency>

2、工具类
● 工具类中参数主要为水印内容、透明度、旋转角度。
● 如果需要其他参数,可直接改为map来传递参数去扩展。

java">package cn.end.less.utils;import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.VerticalAlignment;import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.FileInputStream;
import java.io.FileOutputStream;public class PPTWatermarkUtil {public static void addWatermark(String path, String outpath, String watermarkText, float alpha, int rotation) throws Exception {// 读取PPT文件FileInputStream fis = new FileInputStream(path);HSLFSlideShow ppt = new HSLFSlideShow(fis);fis.close();// 添加水印for (HSLFSlide slide : ppt.getSlides()) {Dimension pageSize = slide.getSlideShow().getPageSize();Integer width = (int) pageSize.getWidth();Integer height = (int) pageSize.getHeight();// 在每张幻灯片上添加文本框HSLFTextBox textBox = slide.createTextBox();textBox.setAnchor(new java.awt.Rectangle(0, 0, width, height));// 设置文本框大小和位置textBox.setVerticalAlignment(VerticalAlignment.MIDDLE);// 设置文本框的文字上下左右居中// 在文本框中添加文本HSLFTextParagraph paragraph = textBox.getTextParagraphs().get(0);HSLFTextRun textRun = paragraph.getTextRuns().get(0);textRun.setText(watermarkText);// 水印内容textRun.setFontSize(48d);// 字体大小textRun.setFontColor(new Color(128, 128, 128, (int) (alpha * 255)));// 设置字体颜色textRun.setBold(true);// 粗体textRun.setItalic(true);// 斜体// 设置文本框的旋转角度Rectangle2D anchor = textBox.getAnchor();double centerX = anchor.getX() + anchor.getWidth() / 2;// 文本框中心点的位置double centerY = anchor.getY() + anchor.getHeight() / 2;textBox.setRotation(rotation);// 设置文本框旋转角度double newCenterX = textBox.getAnchor().getX() + textBox.getAnchor().getWidth() / 2;// 文本框中心点在幻灯片中心点的偏移量double newCenterY = textBox.getAnchor().getY() + textBox.getAnchor().getHeight() / 2;double dx = newCenterX - centerX;double dy = newCenterY - centerY;// 旋转后文本框中心点与旋转前中心点的偏移量textBox.setAnchor(new java.awt.Rectangle((int) (anchor.getX() - dx),(int) (anchor.getX() - dy),(int) anchor.getWidth(),(int) anchor.getHeight()));}// 保存PPT文件FileOutputStream fos = new FileOutputStream(outpath);ppt.write(fos);fos.close();}
}

3、主程序

javascript">private static String path= "F:\\临时\\测试.pptx";
private static String outpath= "F:\\临时\\测试11.pptx";public  static void main(String[] args) throws Exception {PPTWatermarkUtil.addWatermark(path, outpath, "我是水印啊", 0.5f, 360-30);
}

其他:
方式二+方式三

java">package cn.end.less.config;import cn.end.less.utils.PPTWatermarkUtil;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.sl.usermodel.PictureData;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class PptWatermark {private static String path= "F:\\临时\\测试.ppt";private static String outpath= "F:\\临时\\测试结果.ppt";public  static void main(String[] args) throws Exception {// 方式二setPPTWaterMark(path,outpath,"我是水印啊");// 方式三test1();}public static void test1() throws Exception{// 读取PPT文件FileInputStream fis = new FileInputStream(path);HSLFSlideShow ppt = new HSLFSlideShow(fis);fis.close();// 添加水印for (HSLFSlide slide : ppt.getSlides()) {Dimension pageSize = slide.getSlideShow().getPageSize();Integer width = (int) pageSize.getWidth();Integer height = (int) pageSize.getHeight();// 在每张幻灯片上添加文本框HSLFTextBox textBox = slide.createTextBox();textBox.setRotation(360-45);// 设置文本框旋转角度textBox.setAnchor(new Rectangle(0, height/4,width , height));// 在文本框中添加文本HSLFTextRun textRun = textBox.getTextParagraphs().get(0).getTextRuns().get(0);textRun.setText("我是水印啊");textRun.setFontSize(48d);textRun.setFontColor(new Color(0,0,0,128));textRun.setBold(true);textRun.setItalic(true);}// 保存PPT文件FileOutputStream fos = new FileOutputStream(outpath);ppt.write(fos);fos.close();}/*** PPT设置图片水印*/public static void setPPTWaterMark(String path, String targetpath, String markStr) {HSLFSlideShow slideShow = null;try {slideShow = new HSLFSlideShow(new FileInputStream(path));} catch (IOException e) {throw new RuntimeException("setPPTWaterMark fail:获取PPT文件失败");}ByteArrayOutputStream os = null;FileOutputStream out = null;try {//获取水印os = getImage(markStr);// 将水印图片添加到幻灯片中,返回的对象中包括了图片的元数据信息PictureData pictureData1 = slideShow.addPicture(os.toByteArray(), PictureData.PictureType.PNG);// 将水印图片添加到每一页幻灯片中for (HSLFSlide slide : slideShow.getSlides()) {HSLFPictureShape pictureShape = slide.createPicture(pictureData1);Dimension pageSize = slide.getSlideShow().getPageSize();
//                Rectangle2D anchor = pictureShape.getAnchor();// 锚点pictureShape.setAnchor(new Rectangle2D.Double(0, 0, pageSize.getWidth(), pageSize.getHeight()));//设置图片的位置和大小 方法}out = new FileOutputStream(targetpath);slideShow.write(out);} catch (IOException e) {throw new RuntimeException("添加水印文件异常:生成ppt水印文件失败");} finally {if (slideShow != null) {try {slideShow.close();} catch (IOException e) {e.printStackTrace();}}if (out != null) {try {out.close();} catch (IOException e) {e.printStackTrace();}}if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 获取水印文字图片流*/private static ByteArrayOutputStream getImage(String text) {ByteArrayOutputStream os = new ByteArrayOutputStream();try {// 导出到字节流BBufferedImage image = createWaterMarkImageBig(text);ImageIO.write(image, "png", os);} catch (Exception e) {
//            log.error("getImage fail: 创建水印图片IO异常", e);
//            throw new Exception(ResultCode.FAILURE, "getImage fail: 创建水印图片IO异常");}return os;}/*** 根据文字生成水印图片(大号 平铺)*/public static BufferedImage createWaterMarkImageBig(String text) {Integer width = 1000; // 水印宽度Integer height = 800; // 水印高度BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象Font font = new Font("宋体", Font.PLAIN, 70);Graphics2D g2d = image.createGraphics();image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);g2d.dispose();g2d = image.createGraphics();//设置字体颜色和透明度g2d.setColor(new Color(0, 0, 0, 60));//设置字体g2d.setStroke(new BasicStroke(1));//设置字体类型  加粗 大小g2d.setFont(font);//设置倾斜度g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);FontRenderContext context = g2d.getFontRenderContext();Rectangle2D bounds = font.getStringBounds(text, context);double x = (width - bounds.getWidth()) / 2;double y = (height - bounds.getHeight()) / 2;double ascent = -bounds.getY();double baseY = y + ascent;//写入水印文字原定高度过小,所以累计写水印,增加高度g2d.drawString(text, (int) x, (int) baseY);//设置透明度g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));//释放对象g2d.dispose();return image;}}

3-Excel加水印

在这里插入图片描述

实现原理:
● Excel水印只能通过生成图片,并将图片置于Excel底层。

代码
1、依赖

<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.14</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>ooxml-schemas</artifactId><version>1.4</version>
</dependency>

2、工具类

java">package cn.end.less.utils;import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;import static java.awt.image.BufferedImage.TYPE_INT_ARGB;/*** @author Alexander* @date 2023/9/7 17:02:44*/
public class ExcelUtil {/*** * @param inputPath 输入路径* @param outputPath 输出路径* @param watermarkText 水印内容*/public static void addWatermark(String inputPath,String outputPath,String watermarkText){try {// 读取Excel文件FileInputStream fis = new FileInputStream(inputPath);XSSFWorkbook workbook = new org.apache.poi.xssf.usermodel.XSSFWorkbook(fis);// 设置文本和字体大小Font font = new Font("宋体",Font.PLAIN,36);int height = 467;int width = 987;float alpha = 0.5f;// 透明度Color textColor = new Color(128, 128, 128, (int) (alpha * 255));// 文本颜色和透明度// 绘制水印图像BufferedImage watermarkImage = drawText(watermarkText, font, textColor, Color.white, height, width);ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();ImageIO.write(watermarkImage, "png", byteArrayOut);// 将水印图像添加到Excel文件中int pictureIdx = workbook.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG);for (int i = 0; i < workbook.getNumberOfSheets(); i++) {XSSFSheet xssfSheet =  workbook.getSheetAt(i);String rID = xssfSheet.addRelation(null, XSSFRelation.IMAGE_PNG, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();//将背景图片设置为工作表xssfSheet.getCTWorksheet().addNewPicture().setId(rID);}// 保存带水印的Excel到输出文件夹File outputDir = new File(outputPath);if (!outputDir.exists()) {outputDir.mkdirs();}String outputFilePath = outputPath + "/测试Excel.xls";FileOutputStream fos = new FileOutputStream(new File(outputFilePath));workbook.write(fos);fos.close();fis.close();} catch (IOException e) {e.printStackTrace();}}/*** 处理水印文字* @param text 水印内容* @param font 颜色* @param textColor 文字颜色* @param backColor 背景颜色* @param height 高度* @param width 宽度* @return*/private static BufferedImage drawText(String text, Font font, Color textColor, Color backColor, double height, double width) {BufferedImage img = new BufferedImage((int) width, (int) height, TYPE_INT_ARGB);Graphics2D loGraphic = img.createGraphics();FontMetrics loFontMetrics = loGraphic.getFontMetrics(font);int liStrWidth = loFontMetrics.stringWidth(text);int liStrHeight = loFontMetrics.getHeight();loGraphic.setColor(backColor);loGraphic.fillRect(0, 0, (int) width, (int) height);// 填充文本的位置loGraphic.translate(((int) width - liStrWidth) / 2, ((int) height - liStrHeight) / 2);loGraphic.rotate(Math.toRadians(-45));// 旋转角度loGraphic.translate(-((int) width - liStrWidth) / 4, -((int) height - liStrHeight) / 4);loGraphic.setFont(font);// 字体loGraphic.setColor(textColor);// 颜色和透明度loGraphic.drawString(text, ((int) width - liStrWidth) / 4, ((int) height - liStrHeight) / 2);loGraphic.drawString(text, ((int) width - liStrWidth) / 2, ((int) height - liStrHeight) / 4);loGraphic.drawString(text, ((int) width - liStrWidth) / 6, ((int) height - liStrHeight) / 20);loGraphic.dispose();return img;}
}

3、测试主方法

javascript">package cn.end.less.utils;public class ExcelTest {private static String inputPath  = "F:/临时/测试.xlsx";private static String outputPath  = "F:/临时/测试结果";private static String watermarkText = "我是水印呐!";public static void main(String[] args)throws Exception{long l = System.currentTimeMillis();ExcelTestUtil1.addWatermark(inputPath,outputPath,watermarkText);long l1 = System.currentTimeMillis();System.out.println("用时:"+(l1-l)/1000);}}

4-PDF加水印

在这里插入图片描述

源代码:
1、依赖

<dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13.1</version>
</dependency>

2、实现类

java">import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.HashMap;/*** @author Alexander* @date 2023/9/18 9:38:51*/
public class PdfUtil {/*** pdf加水印* @param inputPath 输入路径* @param outPath 输出路径* @param markStr 水印内容* @throws Exception*/public static void setPdfWatermark(String inputPath, String outPath, String markStr)throws Exception{File file = new File(outPath);if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}}BufferedOutputStream bufferOut = null;try {bufferOut = new BufferedOutputStream(new FileOutputStream(file));} catch (FileNotFoundException e1) {e1.printStackTrace();}PdfReader reader = new PdfReader(inputPath);PdfStamper stamper = new PdfStamper(reader, bufferOut);PdfContentByte content;BaseFont base = null;// 设置字体库try {base = BaseFont.createFont("C:\\Windows\\Fonts\\SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);} catch (Exception e) {e.printStackTrace();}PdfGState gs = new PdfGState();// 获取文件总页数int total = reader.getNumberOfPages() + 1;for (int i = 1; i < total; i++) {content = stamper.getOverContent(i);// 在内容上方加水印gs.setFillOpacity(0.2f); // 透明度content.beginText();content.setFontAndSize(base, 50);// 字体大小content.setRGBColorFill(220, 20, 60); // 颜色content.setTextMatrix(100, 250);content.showTextAligned(Element.ALIGN_CENTER, markStr, 250, 400, 55);// 旋转角度content.endText();}stamper.close();try {bufferOut.flush();bufferOut.close();} catch (Exception e) {e.printStackTrace();}}}

3、测试

javascript">public static void main(String[] args) {try {setPdfWatermark("F:\\临时\\测试.pdf", "F:\\临时\\测试结果.pdf", "我是水印");} catch (Exception e) {e.printStackTrace();}
}

http://www.ppmy.cn/news/1503599.html

相关文章

【AIGC】Llama-3 官方技术报告

Llama-3 技术报告&#xff08;中文翻译&#xff09; 欢迎关注【youcans的AGI学习笔记】原创作品 0. 简介 现代人工智能&#xff08;AI&#xff09;系统的核心驱动力来自于基础模型。 本文介绍了一组新的基础模型&#xff0c;称为 Llama 3。它是一个语言模型系列&#xff0c;原…

【Android】数据存储之SQLite数据库知识总结

文章目录 SQL数据类型创建表格删除表格修改表格 数据库管理器SQLiteDatabase数据库的创建与删除 SQLiteOpenHelper使用步骤新建数据库操作类增删改查方法使用 SQLite 数据库版本更新 相关知识点ContentValues 类Cursor SQL SQL本质上是一种编程语言&#xff0c;它的学名叫作&qu…

群晖NAS结合内网穿透工具实现远程连接内网SFTP服务传输文件

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

SAP ERP 通过SAP PO LDAP适配器与微软AD域服务系统集成案例

一、客户介绍 上海某芯片制造公司的主要产品应用于图像传感器、 图像信号处理芯片、 低功耗芯片、 射频芯片等。专注集成电路技术开发与制造&#xff0c;服务于图像传感器、图形图像信号处理芯片、低功耗芯片、射频芯片等领域的全球客户。 二、项目需求 该企业内部办公电…

一文看懂Java反射、注解、UML图和Lambda表达式

反射 定义: 反射是 java 开发语言的特征之一&#xff0c;它允许 java 程序对自身进行检查(自审)&#xff0c;并能直接操作程序内部属性&#xff0c;即就是将类中的各种成分映射成一个 java 对象&#xff0c;利用反射技术可以对一个类进行解剖&#xff0c;将各个组成部分映射成…

LinkedList 实现 LRU 缓存

LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;缓存是一种缓存淘汰策略&#xff0c;用于在缓存满时淘汰最久未使用的元素。 关键&#xff1a; 缓存选什么结构&#xff1f; 怎么实现访问顺序&#xff1f; import java.util.*;public class LRUCac…

第十九天培训笔记

上午 1 、构建 vue 发行版本 [rootserver eleme_web]# nohup npm run serve& // 运行 vue 项目 [rootserver eleme_web]# mkdir /eleme [rootserver eleme_web]# cp -r /root/eleme_web/dist/* /eleme/ // 将项目整体 移动到 /eleme 目录下 [rootserver eleme_web]# …

vue3实现面包屑-基础实现

1.在默认路由router文件下新增两个额外的文件page&#xff1a;存放额外的路由列表&#xff0c;注意这里需要引入有router-view视图的页面&#xff0c;这里我是采用let Main () > import("v/layout/Main.vue");代码&#xff1a; 在page中使用&#xff1a; 2.dyna…