代码:
package com.jc.util; 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.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; import java.util.Map; import javax.imageio.ImageIO; import javax.swing.JLabel; import com.itextpdf.text.BaseColor; 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; /** * 水印工具类 * @author wang-xiaoming */ public class WaterMarkUtil { // 水印透明度 private static float alpha = 0.5f; // 水印之间的间隔 private static final int XMOVE = 80; // 水印之间的间隔 private static final int YMOVE = 80; // 默认文字信息 private static final String DEFAULT_MSG = "防伪水印"; // 默认文字字体 private static final String DEFAULT_MSGFONT = "仿宋"; // 默认文字大小 private static final int DEFAULT_FONTSIZE = 20; // 默认文字颜色,色彩代码:https://html-color-codes.info/chinese/ private static final String DEFAULT_MSGCOLOR = "#848484"; /** * 用户信息文字 */ private static final String MSG = "msg"; /** * 用户信息字体 */ private static final String MSGFONT = "msgFont"; /** * 用户信息文字大小 */ private static final String MSGSIZE = "msgSize"; /** * 用户信息文字颜色 */ private static final String MSGCOLOR = "msgColor"; /** * 用户信息文字字体 */ private static final String MSGFORMAT = "msgFormat"; /** * 倾斜度 */ private static final String DEGREE = "degree"; /** * 获取文本长度。汉字为1:1,英文和数字为2:1 */ private static int getTextLength (String text) { int length = text.length (); for (int i = 0; i < text.length (); i++) { String s = String.valueOf (text.charAt (i)); if (s.getBytes ().length > 1) { length++; } } length = length % 2 == 0 ? length / 2 : length / 2 + 1; return length; } /** * RGB 转 Color * @param colorCode,十六进制颜色码,#0000FF * @return */ private static Color parseToColor(String colorCode) { String srcColorCode = colorCode; Color convertedColor = Color.white; try { colorCode = colorCode.replace("#", ""); convertedColor = new Color(Integer.parseInt(colorCode, 16)); } catch(NumberFormatException e) { System.out.println("RGB 转 Color异常,e=" + e.getMessage()); } System.out.println("RGB 转 Color," + srcColorCode + " --> " + convertedColor); return convertedColor; } /** * RGB 转 BaseColor * @param colorCode,十六进制颜色码,#0000FF * @return */ private static BaseColor parseToBaseColor(String colorCode) { BaseColor convertedColor = BaseColor.WHITE; try { colorCode = colorCode.replace("#", ""); int red = Integer.parseInt(colorCode.substring(0, 2), 16); int green = Integer.parseInt(colorCode.substring(2, 4), 16); int blue = Integer.parseInt(colorCode.substring(4, 6), 16); convertedColor = new BaseColor(red, green, blue); } catch(NumberFormatException e) { System.out.println("RGB 转 BaseColor异常,e=" + e.getMessage()); } return convertedColor; } /** * 图片添加文字水印 * @param paramMap * @param srcImgPath 原图片路径 * @param targetPath 目标图片路径 */ public static void addWaterMarkToImage (Map<String, String> paramMap, String srcImgPath, String targetPath) { String msg = StringUtil.isNullOrEmpty(paramMap.get(MSG))? DEFAULT_MSG:paramMap.get(MSG);// 文字信息 String fontType = StringUtil.isNullOrEmpty(paramMap.get(MSGFONT))? DEFAULT_MSGFONT:paramMap.get(MSGFONT);// 文字字体 int fontSize = StringUtil.toInt(paramMap.get(MSGSIZE), DEFAULT_FONTSIZE);// 文字大小 String msgColor = StringUtil.isNullOrEmpty(paramMap.get(MSGCOLOR))? DEFAULT_MSGCOLOR:paramMap.get(MSGCOLOR);// 文字颜色 Color color = parseToColor(msgColor); int plate = StringUtil.toInt(paramMap.get(MSGFORMAT), 1);// 文字板式 1-倾斜(-45°);2-水平(0°) Integer degree = plate == 1? -45:0; if(paramMap.get(DEGREE) != null){ degree = Integer.valueOf(paramMap.get(DEGREE)); } InputStream is = null; OutputStream os = null; try { // 源图片 Image srcImg = ImageIO.read (new File (srcImgPath)); int width = srcImg.getWidth (null);// 原图宽度 int height = srcImg.getHeight (null);// 原图高度 BufferedImage buffImg = new BufferedImage (srcImg.getWidth (null), srcImg.getHeight (null), BufferedImage.TYPE_INT_RGB); // 得到画笔对象 Graphics2D g = buffImg.createGraphics (); // 设置对线段的锯齿状边缘处理 g.setRenderingHint (RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage (srcImg.getScaledInstance (srcImg.getWidth (null), srcImg.getHeight (null), Image.SCALE_SMOOTH), 0, 0, null); // 设置水印旋转 if (null != degree) { g.rotate (Math.toRadians (degree), (double) buffImg.getWidth () / 2, (double) buffImg.getHeight () / 2); } // 设置水印文字颜色 g.setColor (color); // 设置水印文字Font Font font = new Font (fontType, Font.BOLD, fontSize); g.setFont (font); // 设置水印文字透明度 g.setComposite (AlphaComposite.getInstance (AlphaComposite.SRC_ATOP, alpha)); int x = -width / 2; int y = -height / 2; int markWidth = fontSize * getTextLength (msg);// 字体长度 int markHeight = fontSize;// 字体高度 // 循环添加水印 while (x < width * 1.5) { y = -height / 2; while (y < height * 1.5) { g.drawString (msg, x, y); y += markHeight + YMOVE; } x += markWidth + XMOVE; } // 释放资源 g.dispose (); // 生成图片 os = new FileOutputStream (targetPath); ImageIO.write (buffImg, "JPG", os); } catch (Exception e) { System.out.println("图片添加文字水印异常!e=" + e.getMessage()); } finally { try { if (null != is) is.close (); } catch (Exception e) { System.out.println("图片添加文字水印异常,关闭is流异常!e=" + e.getMessage()); } try { if (null != os) os.close (); } catch (Exception e) { System.out.println("图片添加文字水印异常,关闭os流异常!e=" + e.getMessage()); } } } /** * 文件添加文字水印 * @param paramMap * @param srcPdfPath 原文件路径 * @param targetPath 目标文件路径 */ public static void addWaterMarkToPDF(Map<String, String> paramMap, String srcPdfPath, String targetPath){ String msg = StringUtil.isNullOrEmpty(paramMap.get(MSG))? DEFAULT_MSG:paramMap.get(MSG);// 文字信息 String fontType = StringUtil.isNullOrEmpty(paramMap.get(MSGFONT))? DEFAULT_MSGFONT:paramMap.get(MSGFONT);// 文字字体 int fontSize = StringUtil.toInt(paramMap.get(MSGSIZE), DEFAULT_FONTSIZE);// 文字大小 String msgColor = StringUtil.isNullOrEmpty(paramMap.get(MSGCOLOR))? DEFAULT_MSGCOLOR:paramMap.get(MSGCOLOR);// 文字颜色 BaseColor baseColor = parseToBaseColor(msgColor); int plate = StringUtil.toInt(paramMap.get(MSGFORMAT), 1);// 文字板式 1-倾斜(45°);2-水平(0°) Integer degree = plate == 1? 45:0; if(paramMap.get(DEGREE) != null){ degree = Integer.valueOf(paramMap.get(DEGREE)); } FileOutputStream fos = null; BufferedOutputStream bos = null; PdfReader reader = null; PdfStamper stamper = null; try { fos = new FileOutputStream(new File(targetPath)); bos = new BufferedOutputStream(fos); reader = new PdfReader(srcPdfPath); stamper = new PdfStamper(reader, bos); // 获取总页数 +1, 下面从1开始遍历 int total = reader.getNumberOfPages() + 1; // 使用classpath下面的字体库,例如,"/SIMFANG.TTF" String fontPath = ""; // 取字体所在真实路径或相对根目录所在路径 String fontsPath = File.separator; if ("仿宋".equals(fontType)) { fontPath = fontsPath + "SIMFANG.TTF"; } else if ("宋体".equals(fontType)) { fontPath = fontsPath + "SIMSUN.TTC,0";// 解决SIMSUN.TTC报错,解决方法http://www.genshuixue.com/i-cxy/p/15543081 } else if ("黑体".equals(fontType)) { fontPath = fontsPath + "SIMHEI.TTF"; } else if ("微软雅黑".equals(fontType)) { fontPath = fontsPath + "MSYH.TTF"; } else { fontPath = fontsPath + "SIMFANG.TTF"; } BaseFont base = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 间隔 int interval = -5; // 获取水印文字的高度和宽度 int textH = 0, textW = 0; JLabel label = new JLabel(); label.setText(msg); 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(alpha); gs.setStrokeOpacity(alpha); 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.setColorFill(baseColor); content.setFontAndSize(base, fontSize); // 获取每一页的高度、宽度 pageSizeWithRotation = reader.getPageSizeWithRotation(i); float pageHeight = pageSizeWithRotation.getHeight(); float pageWidth = pageSizeWithRotation.getWidth(); if(i < 2){ System.out.println("-----------第" + i + "张----------"); System.out.println("pageHeight:" + pageHeight); System.out.println("pageWidth:" + pageWidth); } // 根据纸张大小多次添加, 水印文字成30度角倾斜 StringBuilder builder; for (int height = interval + textH; height < pageHeight*2; height = height + textH * 3) { builder = new StringBuilder("(x, y) = "); for (int width = interval + textW; width < (pageWidth + textW)*2; width = width + textW * 2) { content.showTextAligned(Element.ALIGN_CENTER, msg, width - textW, height - textH, degree); builder.append("(").append(width - textW).append(", ").append(height - textH).append(")\t"); } if(i < 2){ System.out.println(builder.toString()); } } content.endText(); } } catch (FileNotFoundException e) { System.out.println("文件添加文字水印异常,FileNotFoundException!e=" + e.getMessage()); } catch (IOException e) { System.out.println("文件添加文字水印异常,IOException!e=" + e.getMessage()); } catch (DocumentException e) { System.out.println("文件添加文字水印异常,DocumentException!e=" + e.getMessage()); } finally { // 关流 try { if(null != stamper){ stamper.close(); } } catch (Exception e) { System.out.println("文件添加文字水印异常,关闭stamper流异常!e=" + e.getMessage()); } try { if(null != reader){ reader.close(); } } catch (Exception e) { System.out.println("文件添加文字水印异常,关闭reader流异常!e=" + e.getMessage()); } try { if(null != fos){ fos.close(); } } catch (Exception e) { System.out.println("文件添加文字水印异常,关闭fos流异常!e=" + e.getMessage()); } try { if(null != bos){ bos.close(); } } catch (Exception e) { System.out.println("文件添加文字水印异常,关闭bos流异常!e=" + e.getMessage()); } } } // public static void main (String[] args) { Map<String, String> paramMap = new HashMap<>(16); /** * 测试一:图片添加文字水印 */ /*// 原图片路径 System.out.println ("图片添加文字水印开始..."); String srcImgPath = "D:/watermark/test/my.png"; // 目标图片路径 String targerPath1 = "D:/watermark/test/my_图片文字水印_水平.png"; String targerPath2 = "D:/watermark/test/my_图片文字水印_倾斜.png"; String targerPath3 = "D:/watermark/test/my_图片文字水印_自定义角度.png"; // 给图片添加正水印文字 paramMap.put(MSGFORMAT, "2"); WaterMarkUtil.addWaterMarkToImage(paramMap, srcImgPath, targerPath1); // 给图片添加斜水印文字 paramMap.put(MSGFORMAT, "1"); WaterMarkUtil.addWaterMarkToImage(paramMap, srcImgPath, targerPath2); // 给图片添加任意斜度水印文字 paramMap.put(DEGREE, "-75"); WaterMarkUtil.addWaterMarkToImage(paramMap, srcImgPath, targerPath3); System.out.println ("图片添加文字水印结束...");*/ /** * 测试二:文件添加文字水印 */ paramMap = new HashMap<>(16); System.out.println ("文件添加文字水印开始..."); // 原图片路径 String srcPdfPath = "D:/watermark/test/my.pdf"; // 目标图片路径 String targerPath4 = "D:/watermark/test/my_pdf文字水印.pdf"; paramMap.put(MSGFORMAT, "1"); paramMap.put(MSG, "花开有时"); WaterMarkUtil.addWaterMarkToPDF(paramMap, srcPdfPath, targerPath4); System.out.println ("文件添加文字水印结束..."); /** * 测试三:文件添加图片水印 TODO */ /** * 测试四:图片添加图片水印 TODO */ } }
测试文件路径:
项目结构:
相关附件请参考评论。
原文:https://www.cnblogs.com/huakaiyoushi/p/13220721.html