java 给图片、pdf、docx、doc、wps、xlsx、xls添加水印(均测试通过)

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-20160307.jar
poi-examples-3.14-20160307.jar
poi-excelant-3.14-20160307.jar
poi-ooxml-3.14-20160307.jar
poi-ooxml-schemas-3.14-20160307.jar
poi-scratchpad-3.14-20160307.jar
xbean.jar
下载地址:https://pan.baidu.com/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、设置水印文字Font
            g.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 block
			e.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使用,实际开发肯定需要进行进一步抽取优化


版权声明:本文为u011293064原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。