首页 > 其他 > 详细

文字水印与图片水印

时间:2020-07-01 19:11:02      阅读:36      评论:0      收藏:0      [点我收藏+]

代码:

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!