Java实现给图片加单个、多个文字水印

完整代码

package com.yuanjia.util;

import java.awt.Color;
import java.awt.Font;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Objects;


public class ImgWaterUtils {

    private final static String IMG_TYPE = "jpg";

    /**
     * 添加单个文字水印到正中间(可以自定义位置)
     *
     * @param waterConfig 水印配置
     * @param bytes       源文件字节数组
     * @param srcImgPath  源文件路径
     * @param targetPath  输出文件路径
     */
    public static void markImageByTextOne(WaterConfig waterConfig, byte[] bytes, String srcImgPath, String targetPath) {
        OutputStream os = null;
        try {
            // 1、源图片
            Image srcImg = getImage(bytes, srcImgPath);
            // 图片宽
            int width = srcImg.getWidth(null);
            // 图片高
            int height = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = assembleGraphics2D(waterConfig, srcImg, width, height, buffImg);
            int size = waterConfig.getFont().getSize();
            int waterWidth = size * getTextLength(waterConfig.getLogText());
            int x = (width - waterWidth) / 2;
            int y = (height - size) / 2;
            // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
            g.drawString(waterConfig.getLogText(), x, y);
            // 9、释放资源
            g.dispose();
            // 10、生成图片
            os = new FileOutputStream(targetPath);
            ImageIO.write(buffImg, IMG_TYPE, os);
            System.out.println("图片完成添加单个水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != os)
                    os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 添加多个文字水印
     *
     * @param waterConfig 水印配置
     * @param bytes       源文件字节数组
     * @param srcImgPath  源文件路径
     * @param targetPath  输出文件路径
     */
    public static void markImageByTextMore(WaterConfig waterConfig, byte[] bytes, String srcImgPath, String targetPath) {
        OutputStream os = null;
        try {
            // 1、源图片
            Image srcImg;
            srcImg = getImage(bytes, srcImgPath);
            int width = srcImg.getWidth(null);
            int height = srcImg.getHeight(null);
            BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = assembleGraphics2D(waterConfig, srcImg, width, height, buffImg);
            int x = -width * 3;
            int y;
            String logText = waterConfig.getLogText();
            int size = waterConfig.getFont().getSize();
            int waterWidth = size * getTextLength(logText);
            int positionWidth = waterConfig.getPositionWidth();
            int positionHeight = waterConfig.getPositionHeight();
            while (x < width * 3) {
                y = -height * 3;
                while (y < height * 3) {
                    g.drawString(logText, x, y);
                    y += size + positionWidth;
                }
                x += waterWidth + positionHeight;
            }
            // 9、释放资源
            g.dispose();
            // 10、生成图片
            os = new FileOutputStream(targetPath);
            ImageIO.write(buffImg, IMG_TYPE, os);
            System.out.println("图片完成添加多个水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static Image getImage(byte[] bytes, String srcImgPath) throws IOException {
        Image srcImg;
        if (Objects.nonNull(bytes)) {
            srcImg = ImageIO.read(new ByteArrayInputStream(bytes));
        } else {
            srcImg = ImageIO.read(new File(srcImgPath));
        }
        return srcImg;
    }


    /**
     * 组装画笔对象
     */
    private static Graphics2D assembleGraphics2D(WaterConfig waterConfig, Image srcImg, int width, int height, BufferedImage buffImg) {
        // 2、得到画笔对象
        Graphics2D g = buffImg.createGraphics();
        // 3、设置对线段的锯齿状边缘处理
        g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g.drawImage(srcImg, 0, 0, width, height, null);
        // 4、设置水印旋转
        if (null != waterConfig.getDegree()) {
            g.rotate(Math.toRadians(waterConfig.getDegree()), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
        }
        // 5、设置水印文字颜色
        g.setColor(waterConfig.getColor());
        // 6、设置水印文字Font
        g.setFont(waterConfig.getFont());
        // 7、设置水印文字透明度
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, waterConfig.getAlpha()));
        // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
        return g;
    }


    /**
     * 计算水印文本长度(1、中文长度即文本长度 2、英文长度为文本长度二分之一)
     */
    public 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;
    }


}


@Data
@NoArgsConstructor
@AllArgsConstructor
class WaterConfig {
    /**
     * 水印透明度
     */
    private float alpha = 0.5f;
    /**
     * 水印横向间隔
     */
    private int positionWidth = 100;
    /**
     * 水印纵向间隔
     */
    private int positionHeight = 100;
    /**
     * 水印文字字体
     */
    private Font font = new Font("宋体", Font.BOLD, 32);
    /**
     * 水印文字颜色
     */
    private Color color = Color.red;
    /**
     * 水印旋转
     */
    private Integer degree = -45;
    /**
     * 水印内容
     */
    private String logText;
}

效果

原图

在这里插入图片描述

单个水印

在这里插入图片描述

多个水印

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值