图片添加水印倾斜、铺满最全工具类

可以动态修改参数调整倾斜以及字体大小、颜色等。

package com.seatrend.electronicrecord.utils;

import sun.font.FontDesignMetrics;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.List;

/**
 * @author: create by simoo
 * @version: v1.0
 * @description: 
 * @date:2022/9/7
 */
public class ImageMarkerUtil {
    /**
     * 给图片添加文字水印
     *
     * @param markerTextList 水印文字(一个集合一个值对应一条水印)
     * @param zpStrByte      源图像byte
     * @param response       返回流
     * @param fontSize       水印字体大小
     * @param color          水印的字体颜色
     * @param alpha          透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
     */
    public static void markerText(List<String> markerTextList,
                                  byte[] zpStrByte, HttpServletResponse response,
                                  int fontSize, Color color, float alpha) {
        if (zpStrByte == null) {
            return;
        }
        try {
            Font font = new Font("宋体", Font.BOLD, fontSize);
            String[] waterMarkContents = markerTextList.stream().toArray(String[]::new);
            // 获取其中最长的文字水印的大小
            int maxLen = 0;
            int maxHigh = 0;
            for (int i = 0; i < waterMarkContents.length; i++) {
                String waterMarkContent = waterMarkContents[i];
                int fontlen = getStringLength(font, waterMarkContent);
                if (fontlen >= maxLen) {
                    maxLen = fontlen;
                }
                maxHigh = maxHigh + (i + 1) * fontSize + 10;
            }

            //byte转为输入流
            InputStream buffin = new ByteArrayInputStream(zpStrByte, 0, zpStrByte.length);
            Image srcImg = ImageIO.read(buffin);//文件转化为图片
            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(color); //设置水印颜色
            g.setFont(font);//设置字体
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));//设置水印文字透明度
            g.rotate(Math.toRadians(-45),  srcImgWidth,  srcImgHeight);//设置水印旋转

            //一个div 每行每列的打印到图片 上
            int rowsNumber = srcImgHeight/maxLen+srcImgHeight%maxLen;// 图片的高  除以  文字水印的宽  打印的行数(以文字水印的宽为间隔)
            int columnsNumber = srcImgWidth/maxLen+srcImgWidth%maxLen;//图片的宽 除以 文字水印的宽  每行打印的列数(以文字水印的宽为间隔)
            //至少打印一次
            if (rowsNumber < 1) {
                rowsNumber = 1;
            }
            if (columnsNumber < 1) {
                columnsNumber = 1;
            }

            int yz = 0;
            //遍历每行打印到图片上的个数
            for (int a = 0; a < columnsNumber; a++) {
                int t = 0;
                for (int j = 0; j < waterMarkContents.length; j++) {
                    String waterMarkContent = waterMarkContents[j];
                    int y = (j + 1) * 40 + 10 + t;

                    // 文字叠加,自动换行叠加,注意符号
                    int tempX = -srcImgWidth / 2;
                    int tempY = -srcImgHeight / 2 + y + yz;
                    // 单字符长度
                    int tempCharLen = 0;
                    // 单行字符总长度临时计算
                    int tempLineLen = 0;
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < waterMarkContent.length(); i++) {
                        char tempChar = waterMarkContent.charAt(i);
                        tempCharLen = getCharLen(tempChar, g);
                        tempLineLen += tempCharLen;

                        // 和图片的长度进行对应的比较操作
                        if (tempLineLen >= srcImgWidth) {
                            // 长度已经满一行,进行文字叠加
                            g.drawString(sb.toString(), tempX, tempY);
                            t = t + 40;
                            // 清空内容,重新追加
                            sb.delete(0, sb.length());
                            tempY += 40;
                            tempLineLen = 0;
                        }
                        // 追加字符
                        sb.append(tempChar);
                    }
                    // 遍历每列打印到图片上的个数
                    for (int z = 0; z < rowsNumber; z++) {
                        // 最后叠加余下的文字
                        g.drawString(sb.toString(), tempX, tempY);
                        tempX = tempX + maxLen + XMOVE;
                    }
                }
                yz = yz + maxHigh + YMOVE;
            }
            g.dispose();// 释放资源
            ImageIO.write(bufImg, "JPEG", response.getOutputStream());// 输出流
        } catch (Exception e) {
            e.printStackTrace();
            e.getMessage();
        }
    }


    /**
     * 水印之间的横向间隔
     */
    private static final int XMOVE = 80;

    /**
     * 水印之间的纵向间隔
     */
    private static final int YMOVE = 80;


    public static int getCharLen(char c, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charWidth(c);
    }


    //得到字符串长度
    public static int getStringLength(Font font, String markContent) {
        if (StringUtils.isEmpty(markContent)) {
            return 0;
        }
        if (null == font) {
            font = new Font(null);
        }
//        FontDesignMetrics metrics = FontDesignMetrics.getMetrics(font);
//
//        char[] strcha = str.toCharArray();
//        int strWidth = metrics.charsWidth(strcha, 0, str.length());
        JLabel label = new JLabel(markContent);
        FontMetrics metrics = label.getFontMetrics(font);
        int width = metrics.stringWidth(label.getText());//文字水印的宽
        return width;
    }
}

每行水印换行借鉴博客地址(如有侵犯,立即删除):https://blog.csdn.net/weixin_46384976/article/details/126390246

 

调用:ImageMarkerUtil.markerText(markList, zpStrByte, response, 30, Color.gray,0.8f);

 

效果:

 

posted @ 2022-10-14 16:43  Simoo23  阅读(284)  评论(0编辑  收藏  举报