SpringBoot实现图片添加水印

1、添加pom依赖

xml 复制代码
<dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>net.coobird</groupId>
            <artifactId>thumbnailator</artifactId>
            <version>0.4.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
</dependency>

2、代码

java 复制代码
import net.coobird.thumbnailator.Thumbnails;

import javax.imageio.ImageIO;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Random;


public class WatermarkUtil {
    private static final List<String> ALLOWED_EXTENSIONS = Arrays.asList("jpg");

    public static void main(String[] args) {
        list();
    }
    public static void list() {
        String path = "F:\\picture\\";
        File file1 = new File(path);
        if (file1.exists()) {
            File path2 = new File("F:\\picture2\\");
            if(!path2.exists()) {
                path2.mkdirs();
            }
            File[] files = file1.listFiles();
            //File file2 = files[0];
            for (int i = 0;i<files.length;i++) {
                File file2 = files[i];
                //带水印版本的名字
                String watermarkName = file2.getName();
                // 创建带水印的文件对象
                //创建带水印且压缩画质的版本
                File newWatermarkName = new File(path2.getAbsolutePath()+"/" + watermarkName);
                try {
                    // 为文件添加水印并压缩
                    addWatermarkAndCompress(file2, newWatermarkName,"微信:grapro666 QQ: 3642795578");
                } catch (IOException e) {
                }
            }
        }
    }

    /**
     * 检查文件名是否允许。
     *
     * 此方法通过检查文件名的扩展名来确定文件名是否被允许。文件名必须包含至少一个点(.)
     * 以标识扩展名,并且扩展名必须在预定义的允许扩展名列表中。
     *
     * @param fileName 要检查的文件名。
     * @return 如果文件名的扩展名被允许,则返回true;否则返回false。
     */
    private Boolean isAllowed(String fileName) {
        // 检查文件名是否为空或不包含点(.)
        if(fileName == null || fileName.lastIndexOf(".") == -1){
            return false;
        }
        // 提取文件名的扩展名,并转换为小写
        String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
        // 检查提取的扩展名是否在允许的扩展名列表中
        return ALLOWED_EXTENSIONS.contains(extension);
    }




    /**
     * 给图片添加水印并压缩保存。
     *
     * 此方法接收原始图片文件、目标输出文件和水印文本作为参数,它将原始图片读入,
     * 添加水印后,按照原始尺寸进行压缩,并保存到目标文件中。
     *
     * @param originalFile 原始图片文件,添加水印和压缩的基础文件。
     * @param outputFile 添加水印并压缩后的图片保存位置。
     * @param watermarkText 要添加的水印文本。
     * @throws IOException 如果读取或写入文件发生错误。
     */
    private static void addWatermarkAndCompress(File originalFile, File outputFile,String watermarkText) throws IOException {
        // 读取原始图片
        BufferedImage originalImage = ImageIO.read(originalFile);
        // 添加水印
        BufferedImage watermarkedImage = addWatermark(originalImage, watermarkText);
        // 获取原图尺寸,以保持压缩后的图片尺寸与原图相同
        // 获取原图尺寸
        int originalWidth = originalImage.getWidth();
        int originalHeight = originalImage.getHeight();

        // 使用Thumbnails.of方法对添加水印后的图片进行缩放和压缩
        // 按比例缩放并压缩
        Thumbnails.of(watermarkedImage)
                .size(originalWidth, originalHeight)
                .outputQuality(0.4) // 调整画质压缩
                .toFile(outputFile);
    }


    /**
     * 给图片添加水印。
     *
     * @param image 原始图片。
     * @param watermarkText 水印文本。
     * @return 添加了水印的图片。
     */
    private static BufferedImage addWatermark(BufferedImage image, String watermarkText) {
        // 获取原始图片的宽度和高度
        int imageWidth = image.getWidth();
        int imageHeight = image.getHeight();
        // 创建Graphics2D对象,用于在图片上绘制水印
        // 创建用于绘制水印的Graphics2D对象
        Graphics2D g2d = (Graphics2D) image.getGraphics();
        // 设置透明度,使水印呈现半透明效果
        // 设置水印的属性
        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f);
        g2d.setComposite(alphaChannel);
        // 设置水印文字颜色为灰色
        g2d.setColor(Color.GRAY);
        // 设置水印文字的字体、大小和样式
        // 使用支持中文的字体,例如SimHei(黑体)
        Font font = new Font("SimHei", Font.BOLD, 40);
        g2d.setFont(font);
        // 获取水印文字的尺寸信息
        FontMetrics fontMetrics = g2d.getFontMetrics();
        Rectangle2D rect = fontMetrics.getStringBounds(watermarkText, g2d);
        int textWidth = (int) rect.getWidth();
        int textHeight = (int) rect.getHeight();
        // 用于随机生成水印位置偏移量
        Random random = new Random();
        // 平铺方式添加水印,通过控制行间距和文字在行内的偏移,实现错落有致的布局效果
        // 平铺方式添加水印,单双行错开并随机偏移
        for (int y = 0; y < imageHeight; y += textHeight + 400) {
            // 判断当前行为偶数行还是奇数行,奇数行文字向右偏移
            boolean oddRow = (y / (textHeight + 400)) % 2 == 0;
            for (int x = oddRow ? 0 : textWidth / 2; x < imageWidth; x += textWidth + 600) {
                // 随机生成水平和垂直偏移量,使水印位置略有变化,避免整齐排列
                int xOffset = random.nextInt(200) - 100; // 随机偏移 -50 到 50 像素
                int yOffset = random.nextInt(100) - 50;  // 随机偏移 -25 到 25 像素
                // 在图片上绘制水印文字,位置略有偏移
                g2d.drawString(watermarkText, x + xOffset, y + yOffset);
            }
        }
        // 释放Graphics2D资源
        g2d.dispose();
        // 返回添加了水印的图片
        return image;
    }
}
相关推荐
悟空码字1 天前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端
皮皮林5513 天前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602735 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840826 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解6 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解6 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记6 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者7 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840827 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解7 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端