图片增加文本水印(右下角)--Java代码实现

一.效果展示

水印前                                                                             水印后

        

二.代码实现 

/**
 * 在给定的图片上添加文本水印。
 *
 * @param sourceImgPath 源图片路径
 * @param waterMarkContent 水印内容,多个内容用逗号分隔
 * @param degreeAngle 设置水印文字的旋转角度,默认为 -45 度
 * @param transparency 设置水印透明度,默认为 1.0(不透明)
 * @return 添加了水印的 BufferedImage 对象
 */
public static BufferedImage addWaterMark(String sourceImgPath,
                                         String waterMarkContent,
                                         Integer degreeAngle,
                                         float transparency) {
    long startTime = System.currentTimeMillis();

    // 初始化变量
    BufferedImage bufImg = null;
    Font font = new Font("宋体", Font.BOLD, 12); // 水印字体、大小
    Color markContentColor = Color.white; // 水印颜色
    Integer degree = degreeAngle; // 设置水印文字的旋转角度
    float alpha = transparency; // 设置水印透明度

    try {
        // 读取源图片文件并转换为 Image 对象
        File srcImgFile = new File(sourceImgPath);
        Image srcImg = ImageIO.read(srcImgFile);

        // 获取图片的宽度和高度
        int srcImgWidth = srcImg.getWidth(null);
        int srcImgHeight = srcImg.getHeight(null);

        // 创建 BufferedImage 对象,用于绘制水印
        bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bufImg.createGraphics();

        // 将原始图片绘制到 BufferedImage 中
        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), (double) bufImg.getWidth(), (double) bufImg.getHeight());
        }

        // 按逗号分隔水印内容
        String[] split = waterMarkContent.split(",");
        int i = 0;

        // 遍历每个水印内容并绘制到图片上
        for (String s : split) {
            // 计算文字的宽度和高度
            FontMetrics fontMetrics = g.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(s);
            int textHeight = fontMetrics.getHeight();

            // 计算文字的位置,放在右下角留一些边距
            int x = srcImgWidth - textWidth - 10; // 10 是右边距
            int y = srcImgHeight - textHeight - 10 * split.length + textHeight * i; //下边距
            i++;

            // 绘制水印文字
            g.drawString(s, x, y);
        }

        // 释放资源
        g.dispose();

        // 记录方法执行结束时间并输出日志
        long endTime = System.currentTimeMillis();
        log.info("文本内容水印生成图片...完成,耗时 " + (endTime - startTime) + " ms");

    } catch (Exception e) {
        e.printStackTrace();
        e.getMessage();
    }

    // 返回添加了水印的 BufferedImage 对象
    return bufImg;
}

这段代码是一个Java方法,用于在给定的图片上添加文本水印。让我来解释一下这段代码的主要功能和一些需要注意的地方:

  1. 方法签名和参数说明

    • addWaterMark 方法接收四个参数:sourceImgPath(源图片路径)、waterMarkContent(水印内容)、degreeAngle(旋转角度)、transparency(透明度)。
    • degreeAngle 和 transparency 是可选参数,分别用于设置水印文字的旋转角度和透明度。
  2. 方法实现

    • 首先,方法开始时记录了当前时间,用于计算方法执行时间。
    • 创建了一个 BufferedImage 对象 bufImg,作为最终生成带水印的图片。
    • 使用 ImageIO.read 从指定路径读取源图片并转换为 Image 对象。
    • 获取源图片的宽度和高度。
    • 创建 Graphics2D 对象 g,并将源图片绘制到 bufImg 中。
    • 设置水印文字的颜色、字体和透明度。
    • 如果提供了 degreeAngle,则设置水印文字的旋转角度。
    • 将 waterMarkContent 按逗号分隔(这里是以逗号分隔)。
    • 遍历分隔后的水印内容,计算每段文字的宽度和高度,并确定其位置(右下角留有一定的边距)。
    • 使用 drawString 方法将每段水印文字绘制到图片上。
    • 释放 Graphics2D 资源,记录方法执行结束时间,并输出日志。
  3. 返回值

    • 返回生成的带水印的 BufferedImage 对象 bufImg

三.测试类 

/**
 *
 * @Description: 图片水印测试类
 * @User: xxx
 * @Date: 2024/8/6
 */
public class ImageWaterMarkTest {


    public static void main(String[] args) throws Exception {

        //原图本地路径、保存图的本地路径
        String sourcePath = "C:\\Users\\zy011\\Desktop\\图片\\Snipaste_2024-05-29_13-53-10.png";
        String targetPath = "C:\\Users\\zy011\\Desktop\\图片\\Snipaste_2024-05-29_13-53-10_Test.png";
        
        //透明度
        float alpha = 1.0f;
        //图片类型
        String IMAGE_TYPE_JPG = "jpg";
        //图片生成水印
        BufferedImage mcdonaldTestImage = ImageWaterMarkUtil.addWaterMark(sourcePath,
                "某某科技有限公司,张三丰,2024年8月6日",  //水印每行用 ,号隔开
                null, alpha);
        //图片无损再次保存 (工具类在下方)
        ImageLossLessUtil.saveLossLessImage(mcdonaldTestImage, targetPath, IMAGE_TYPE_JPG);
    }
}

附图片无损保存工具

/**
 * Description 无损操作图片
 * ProjectName imagetool
 * Version 1.0
 */

public class ImageLossLessUtil {

    /**
     * @Description 把图片无损再次保存
     * @Date  2022/4/18 13:48
     * @param sourceImgPath - 原始文件路径
     * @param targetImgPath - 目标文件路径
     * @param suffix - 文件格式
     * @return void
     **/
    public static void saveLossLessImage(String sourceImgPath,String targetImgPath,String suffix) throws Exception{
        BufferedImage image = ImageIO.read(new File(sourceImgPath));
        saveLossLessImage(image,targetImgPath,suffix);
    }

    /**
     * @Description 把图片无损再次保存
     * @Date  2022/4/18 13:48
     * @param image -  BufferedImage对象
     * @param targetImgPath - 目标文件路径
     * @param suffix - 文件格式
     * @return void
     **/
    public static void saveLossLessImage(BufferedImage image,String targetImgPath,String suffix) throws Exception{
        //不压缩图片质量进行保存
        ImageWriter writer = ImageIO.getImageWritersBySuffix(suffix).next();
        ImageWriteParam imageWriteParam = writer.getDefaultWriteParam();
        imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        //0-1范围 越大质量越高
        imageWriteParam.setCompressionQuality(1);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        writer.setOutput(new MemoryCacheImageOutputStream(output));
        writer.write(null,new IIOImage(image,null,null),imageWriteParam);
        writer.dispose();
        //最终图片保存路径
        FileOutputStream file = new FileOutputStream(targetImgPath);
        file.write(output.toByteArray());
        file.close();
        output.close();
    }

}

好,以上就是全部内容,能坚持看到这里,你一定很有收获,那么动一动拿offer的小手,点个赞再走吧,听说这么做的人2024年都交了好运!!!

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值