java 添加水印(均亲自测试通过)
前言
本地开发环境:jdk1.8
涉及jar:
1)图片:jdk自带的rt.jar
2)pdf:itextpdf-5.5.9.jar、itext-asian.jar
3)docx、doc、wps:aspectjweaver-1.9.1.jar、aspose-words-14.9.0-jdk16.jar
4)xlsx、xls、et(金山的表格格式):
commons-codec-1.4.jar、
poi-3.14-0307.jar
poi-examples-3.14-0307.jar
poi-excelant-3.14-0307.jar
poi-ooxml-3.14-0307.jar
poi-ooxml-schemas-3.14-0307.jar
poi-scratchpad-3.14-0307.jar
xbean.jar
下载地址:/s/1iEwcOewDG-vGJLtO1NWMcQ
提取码:7df3
正文
1、给图片、pdf添加水印
package com.xxxxx.waterMark;import java.awt.AlphaComposite;import java.awt.Color;import java.awt.Font;import java.awt.FontMetrics;import java.awt.Graphics2D;import java.awt.Image;import java.awt.RenderingHints;import java.awt.image.BufferedImage;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.imageio.ImageIO;import javax.swing.ImageIcon;import javax.swing.JLabel;import com.itextpdf.text.DocumentException;import com.itextpdf.text.Element;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;/*** itextpdf-5.5.9.jar、itext-asian.jar* @author sunshine**/public class WaterMarkUtils {public static String filePath="C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\";/*** @param args* @throws IOException * @throws DocumentException */public static void main(String[] args) throws DocumentException, IOException {// 1、给图片添加文字水印WaterMarkUtils.setWaterMarkToImageByWords("sunshine", WaterMarkWordUtils.filePath+"1.jpg", WaterMarkWordUtils.filePath+"To1.jpg", 45, Color.blue); //2、PDF添加动态水印//要输出的pdf文件BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\To3.pdf")));// 将pdf文件先加水印然后输出WaterMarkUtils.setWaterMarkToPdfByWords(bos, "C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\3.pdf", "sunshine");}//============================================1、给图片添加文字水印==================================================/*** 图片添加文字水印* @param logoText* @param srcImgPath* @param newImagePath* @param degree* @param color*/public static void setWaterMarkToImageByWords(String logoText, String srcImgPath,String newImagePath,Integer degree,Color color) {InputStream is = null;OutputStream os = null;try {// 1、源图片java.awt.Image srcImg = ImageIO.read(new File(srcImgPath));BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);// 2、得到画笔对象Graphics2D g = buffImg.createGraphics();// 3、设置对线段的锯齿状边缘处理g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), java.awt.Image.SCALE_SMOOTH), 0, 0, null);// 4、设置水印旋转if (null != degree) {g.rotate(Math.toRadians(degree), buffImg.getWidth()/2,buffImg.getHeight() /2);}// 5、设置水印文字颜色g.setColor(color);// 6、设置水印文字Fontg.setFont(new java.awt.Font("宋体", java.awt.Font.BOLD, buffImg.getHeight() /2));// 7、设置水印文字透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.45f));// 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)g.drawString(logoText, buffImg.getWidth()/4 , buffImg.getHeight()/4);// 9、释放资源g.dispose();// 10、图片后缀 String formaName = srcImgPath.substring(srcImgPath.lastIndexOf(".")+1, srcImgPath.length());// 11、生成图片os = new FileOutputStream(newImagePath);ImageIO.write(buffImg, formaName, os);} 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();}}}//============================================2、PDF添加动态文字水印==================================================/*** * @param bos输出文件的位置* @param input* 原PDF位置* @param waterMarkName* 页脚添加水印* @throws DocumentException* @throws IOException*/public static void setWaterMarkToPdfByWords(BufferedOutputStream bos, String input, String waterMarkName)throws DocumentException, IOException {PdfReader reader = new PdfReader(input);PdfStamper stamper = new PdfStamper(reader, bos);// 获取总页数 +1, 下面从1开始遍历int total = reader.getNumberOfPages() + 1;// 使用classpath下面的字体库BaseFont base = null;try {base = BaseFont.createFont("C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\Fonts\\calibri.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_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.4f);gs.setStrokeOpacity(0.4f);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();}}
2、给docx、doc、wps、xlsx、xls加水印
package com.xxxxx.waterMark;import java.awt.Color;import java.awt.Font;import java.awt.FontMetrics;import java.awt.Graphics;import java.awt.Rectangle;import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.imageio.ImageIO;import org.apache.poi.hssf.usermodel.HSSFSheet;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.ss.usermodel.ClientAnchor;import org.apache.poi.ss.usermodel.Drawing;import org.apache.poi.ss.usermodel.Picture;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFSheet;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import com.aspose.words.Document;import com.aspose.words.HeaderFooter;import com.aspose.words.HeaderFooterType;import com.aspose.words.HorizontalAlignment;import com.aspose.words.Paragraph;import com.aspose.words.RelativeHorizontalPosition;import com.aspose.words.RelativeVerticalPosition;import com.aspose.words.SaveFormat;import com.aspose.words.Section;import com.aspose.words.Shape;import com.aspose.words.ShapeType;import com.aspose.words.VerticalAlignment;import com.aspose.words.WrapType;public class WaterMarkWordUtils {//文件路径public static String filePath="C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\";public static void main(String[] args) {try {//1、给docx加水印//WaterMarkWordUtils.setWaterMarkToDocxWps("sunshine");//2、给doc加水印//WaterMarkWordUtils.setWaterMarkToDoc("sunshine");//3、给excel加水印//WaterMarkWordUtils.setWaterMarkToXlsx("sunshine");WaterMarkWordUtils.setWaterMarkToXlsEt("sunshine");} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}//============================================1、docx、wps添加文字水印==================================================/*** docx添加水印* @param docx 需要添加水印的word文档* @param watermark 水印文字内容* @throws Exception*/public static void setWaterMarkToDocxWps(String watermarkText) throws Exception {//获取文件输出流//FileOutputStream os = new FileOutputStream(WaterMarkWordUtils.filePath+"To4.docx");FileOutputStream os = new FileOutputStream(WaterMarkWordUtils.filePath+"To9.wps");//获取Doc文档对象模型//Document doc = new Document(WaterMarkWordUtils.filePath+"4.docx");Document doc = new Document(WaterMarkWordUtils.filePath+"9.wps");Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);//水印内容watermark.getTextPath().setText(watermarkText);//水印字体watermark.getTextPath().setFontFamily("宋体");//水印宽度watermark.setWidth(500);//水印高度watermark.setHeight(100);//旋转水印watermark.setRotation(-40);//水印颜色watermark.getFill().setColor(Color.lightGray); watermark.setStrokeColor(Color.lightGray); watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);watermark.setWrapType(WrapType.NONE);watermark.setVerticalAlignment(VerticalAlignment.CENTER);watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);Paragraph watermarkPara = new Paragraph(doc);watermarkPara.appendChild(watermark);for (Section sect : doc.getSections()){insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);}System.out.println("Watermark Set");doc.save(os, SaveFormat.DOCX);//关闭输出流if(os!=null){os.close();}}//============================================2、doc添加水印==================================================/*** 给doc加水印*/public static void setWaterMarkToDoc(String watermarkText) throws Exception{//获取文件输出流FileOutputStream os = new FileOutputStream(WaterMarkWordUtils.filePath+"To5.doc");//FileOutputStream os = new FileOutputStream(WaterMarkWordUtils.filePath+"To10.wpt");//获取Doc文档对象模型Document doc = new Document(WaterMarkWordUtils.filePath+"5.doc");//Document doc = new Document(WaterMarkWordUtils.filePath+"10.wpt");Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);//水印内容watermark.getTextPath().setText(watermarkText);//水印字体watermark.getTextPath().setFontFamily("宋体");//水印宽度watermark.setWidth(500);//水印高度watermark.setHeight(100);//旋转水印watermark.setRotation(-40);//水印颜色watermark.getFill().setColor(Color.lightGray); watermark.setStrokeColor(Color.lightGray); watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);watermark.setWrapType(WrapType.NONE);watermark.setVerticalAlignment(VerticalAlignment.CENTER);watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);Paragraph watermarkPara = new Paragraph(doc);watermarkPara.appendChild(watermark);for (Section sect : doc.getSections()){insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);}System.out.println("Watermark Set");doc.save(os, SaveFormat.DOC);//关闭输出流if(os!=null){os.close();}}/*** 在页眉中插入水印* @param watermarkPara* @param sect* @param headerType* @throws Exception*/private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception{HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);if (header == null){header = new HeaderFooter(sect.getDocument(), headerType);sect.getHeadersFooters().add(header);}header.appendChild(watermarkPara.deepClone(true));}//============================================3、excel添加水印==================================================/*** xlsx添加水印* @param watermarkText* @throws Exception*/public static void setWaterMarkToXlsx(String watermarkText) throws Exception{XSSFWorkbook wb = new XSSFWorkbook(new FileInputStream(WaterMarkWordUtils.filePath+"7.xlsx"));XSSFSheet sheet = wb.getSheetAt(0);//测试暂取第一个工作簿//添加水印WaterMarkWordUtils.waterMarkExcel(wb,sheet,watermarkText);ByteArrayOutputStream bos = new ByteArrayOutputStream();wb.write(bos);wb.close();byte[] content = bos.toByteArray();OutputStream out = null;out = new FileOutputStream(WaterMarkWordUtils.filePath+"To7.xlsx");out.write(content);bos.close();out.close();}/*** xls、et(金山)添加水印* @param watermarkText* @throws Exception*/public static void setWaterMarkToXlsEt(String watermarkText) throws Exception{//HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(WaterMarkWordUtils.filePath+"8.xls"));HSSFWorkbook wb = new HSSFWorkbook(new FileInputStream(WaterMarkWordUtils.filePath+"11.et"));HSSFSheet sheet = wb.getSheetAt(0);//测试暂取第一个工作簿//添加水印WaterMarkWordUtils.waterMarkExcel(wb,sheet,watermarkText);ByteArrayOutputStream bos = new ByteArrayOutputStream();wb.write(bos);wb.close();byte[] content = bos.toByteArray();OutputStream out = null;//out = new FileOutputStream(WaterMarkWordUtils.filePath+"To8.xls");out = new FileOutputStream(WaterMarkWordUtils.filePath+"To11.et");out.write(content);bos.close();out.close();}/*** * @param wb* @param sheet 需要打水印的excel工作簿* @param imPath 水印文字*/private static void waterMarkExcel(Workbook wb,Sheet sheet,String watermarkText) throws Exception {ByteArrayOutputStream ByteArrayOut = new ByteArrayOutputStream();//加载图片/*InputStream imageIn = new FileInputStream(imPath);BufferedImage bufferImg = ImageIO.read(imageIn);*/BufferedImage bufferImg =ImageUtil.getImage(watermarkText);ImageIO.write(bufferImg, "png", ByteArrayOut);//开始打水印Drawing drawing = sheet.createDrawingPatriarch();//ClientAnchor anchor = drawing.createAnchor(1, 1, 2, 2, 1, 1, 2, 2);Picture pic = drawing.createPicture(anchor,wb.addPicture(ByteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG));pic.resize();} }
上面“excel添加水印”的方法中,是生成了一个带文字的水印图片,然后把图片加到excel中,“生成带文字的水印图片”的方法整理了工具类,如下:
package com.xxxxx.waterMark;import java.awt.AlphaComposite;import java.awt.Color;import java.awt.Font;import java.awt.Graphics2D;import java.awt.Image;import java.awt.image.BufferedImage;import java.io.File;import java.io.OutputStream;import javax.imageio.ImageIO;import javax.swing.ImageIcon;public class ImageUtil {public static void main(String[] args) {try {ImageUtil.getImage("sunshine");} catch (Exception e) {e.printStackTrace();}}/*** 创建新的图片*/public static BufferedImage getImage(String waterMarkContent) throws Exception {int width = 150;int height =150;BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g2 = (Graphics2D) bi.getGraphics();g2.setBackground(Color.WHITE);g2.clearRect(0, 0, width, height);return addWatermark(bi, waterMarkContent);}/*** @description 生成水印图片* @param sourceImgPath 源图片路径* @param waterMarkContent 水印内容*/public static BufferedImage addWatermark(BufferedImage sourceImgPath, String waterMarkContent) {// 水印字体,大小Font font = new Font("宋体", Font.BOLD, 28);// 水印颜色Color markContentColor = Color.blue;// 设置水印文字的旋转角度Integer degree = -45;// 设置水印透明度float alpha = 0.5f;OutputStream outImgStream = null;try {// 文件转化为图片Image srcImg = sourceImgPath;// 获取图片的宽int srcImgWidth = srcImg.getWidth(null);// 获取图片的高int srcImgHeight = srcImg.getHeight(null);// 加水印BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);// 得到画笔Graphics2D g = bufImg.createGraphics();g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);// 设置水印颜色g.setColor(markContentColor);// 设置字体g.setFont(font);// 设置水印文字透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));if (null != degree) {// 设置水印旋转g.rotate(Math.toRadians(degree));}// 画出水印,并设置水印位置g.drawString(waterMarkContent, -88, 120);// 释放资源g.dispose();return transferAlpha(bufImg);} catch (Exception e) {e.printStackTrace();e.getMessage();} finally {try {if (outImgStream != null) {outImgStream.flush();outImgStream.close();}} catch (Exception e) {e.printStackTrace();e.getMessage();}}return null;}/*** @description 转化成透明背景的图片* @param bufImg 源图片*/public static BufferedImage transferAlpha(BufferedImage bufImg) {try {Image image = bufImg;ImageIcon imageIcon = new ImageIcon(image);BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),BufferedImage.TYPE_4BYTE_ABGR);Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());int alpha = 0;for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) {for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) {int rgb = bufferedImage.getRGB(j2, j1);int R = (rgb & 0xff0000) >> 16;int G = (rgb & 0xff00) >> 8;int B = (rgb & 0xff);if (((255 - R) < 30) && ((255 - G) < 30) && ((255 - B) < 30)) {rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff);}bufferedImage.setRGB(j2, j1, rgb);}}g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());// 直接输出文件用来测试结果//ImageIO.write(bufImg, "png", new File("C:\\Users\\sunshine\\Desktop\\工作\\waterMark\\8-1.png"));return bufferedImage;} catch (Exception e) {e.printStackTrace();} finally {}return null;}}
以上方法均亲自测试通过,仅作为demo使用,实际开发肯定需要进行进一步抽取优化