Java图片水印案例

wen java案例 5

本文目录导读:

Java图片水印案例

  1. 基础工具类实现
  2. 增强版水印服务
  3. 测试类
  4. Web应用集成示例
  5. 使用说明与注意事项
  6. 注意事项

我来为您提供一个完整的Java图片水印案例,包括文字水印和图片水印两种实现方式。

基础工具类实现

ImageWatermarkUtil.java

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
 * 图片水印工具类
 */
public class ImageWatermarkUtil {
    /**
     * 添加文字水印
     * @param sourcePath 源图片路径
     * @param targetPath 目标图片路径
     * @param watermarkText 水印文字
     * @param fontStyle 字体样式
     * @param fontSize 字体大小
     * @param color 水印颜色
     * @param alpha 透明度(0.0-1.0)
     * @param x 水印x坐标
     * @param y 水印y坐标
     */
    public static void addTextWatermark(String sourcePath, String targetPath,
                                        String watermarkText, int fontStyle,
                                        int fontSize, Color color,
                                        float alpha, int x, int y) {
        try {
            // 读取原图片
            Image image = ImageIO.read(new File(sourcePath));
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            // 创建BufferedImage
            BufferedImage bufferedImage = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
            // 绘制原图
            g2d.drawImage(image, 0, 0, null);
            // 设置水印透明度
            AlphaComposite alphaComposite = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, alpha);
            g2d.setComposite(alphaComposite);
            // 设置字体和颜色
            g2d.setFont(new Font("微软雅黑", fontStyle, fontSize));
            g2d.setColor(color);
            // 绘制文字水印
            g2d.drawString(watermarkText, x, y);
            // 释放资源
            g2d.dispose();
            // 输出图片
            ImageIO.write(bufferedImage, getExtension(targetPath), new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加文字水印(居中对角线平铺)
     */
    public static void addTextWatermarkTile(String sourcePath, String targetPath,
                                            String watermarkText, int fontStyle,
                                            int fontSize, Color color, float alpha) {
        try {
            Image image = ImageIO.read(new File(sourcePath));
            int width = image.getWidth(null);
            int height = image.getHeight(null);
            BufferedImage bufferedImage = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
            g2d.drawImage(image, 0, 0, null);
            // 设置透明度
            AlphaComposite alphaComposite = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, alpha);
            g2d.setComposite(alphaComposite);
            g2d.setFont(new Font("微软雅黑", fontStyle, fontSize));
            g2d.setColor(color);
            // 计算字体尺寸
            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(watermarkText);
            int textHeight = fontMetrics.getHeight();
            // 平铺水印
            for (int posX = -textWidth; posX < width; posX += textWidth * 2) {
                for (int posY = -textHeight; posY < height; posY += textHeight * 2) {
                    g2d.drawString(watermarkText, posX, posY);
                }
            }
            g2d.dispose();
            ImageIO.write(bufferedImage, getExtension(targetPath), new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加图片水印
     * @param sourcePath 源图片路径
     * @param watermarkPath 水印图片路径
     * @param targetPath 目标图片路径
     * @param alpha 透明度
     * @param x 水印x坐标
     * @param y 水印y坐标
     * @param scale 水印缩放比例(1.0为原尺寸)
     */
    public static void addImageWatermark(String sourcePath, String watermarkPath,
                                         String targetPath, float alpha,
                                         int x, int y, double scale) {
        try {
            // 读取原图和水印图
            BufferedImage sourceImage = ImageIO.read(new File(sourcePath));
            BufferedImage watermarkImage = ImageIO.read(new File(watermarkPath));
            int width = sourceImage.getWidth(null);
            int height = sourceImage.getHeight(null);
            // 缩放水印
            int watermarkWidth = (int)(watermarkImage.getWidth() * scale);
            int watermarkHeight = (int)(watermarkImage.getHeight() * scale);
            BufferedImage bufferedImage = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = (Graphics2D) bufferedImage.getGraphics();
            // 绘制原图
            g2d.drawImage(sourceImage, 0, 0, null);
            // 设置透明度
            AlphaComposite alphaComposite = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, alpha);
            g2d.setComposite(alphaComposite);
            // 绘制水印图片
            g2d.drawImage(watermarkImage, x, y, watermarkWidth, watermarkHeight, null);
            g2d.dispose();
            ImageIO.write(bufferedImage, getExtension(targetPath), new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加图片水印(默认位置:右下角)
     */
    public static void addImageWatermarkBottomRight(String sourcePath, 
                                                    String watermarkPath,
                                                    String targetPath, float alpha) {
        try {
            BufferedImage sourceImage = ImageIO.read(new File(sourcePath));
            BufferedImage watermarkImage = ImageIO.read(new File(watermarkPath));
            int width = sourceImage.getWidth();
            int height = sourceImage.getHeight();
            int watermarkWidth = watermarkImage.getWidth();
            int watermarkHeight = watermarkImage.getHeight();
            // 计算右下角位置,留10px边距
            int x = width - watermarkWidth - 10;
            int y = height - watermarkHeight - 10;
            addImageWatermark(sourcePath, watermarkPath, targetPath, alpha, x, y, 1.0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取文件扩展名
     */
    private static String getExtension(String path) {
        int lastIndexOfDot = path.lastIndexOf(".");
        return path.substring(lastIndexOfDot + 1);
    }
}

增强版水印服务

WatermarkService.java

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
/**
 * 水印服务类 - 更丰富的功能
 */
public class WatermarkService {
    /**
     * 添加旋转文字水印
     */
    public static void addRotatedTextWatermark(String sourcePath, String targetPath,
                                               String text, float alpha, boolean tile) {
        try {
            BufferedImage sourceImage = ImageIO.read(new File(sourcePath));
            int width = sourceImage.getWidth();
            int height = sourceImage.getHeight();
            BufferedImage watermarkImage = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d = (Graphics2D) watermarkImage.getGraphics();
            // 设置字体
            g2d.setFont(new Font("楷体", Font.BOLD, 30));
            g2d.setColor(new Color(255, 255, 255));
            // 旋转45度
            g2d.rotate(Math.toRadians(-45), width / 2.0, height / 2.0);
            if (tile) {
                // 平铺模式
                FontMetrics fontMetrics = g2d.getFontMetrics();
                int textWidth = fontMetrics.stringWidth(text);
                int textHeight = fontMetrics.getHeight();
                for (int x = -textWidth; x < width * 1.5; x += textWidth * 2 + 50) {
                    for (int y = -textHeight; y < height * 1.5; y += textHeight * 2 + 50) {
                        g2d.drawString(text, x, y);
                    }
                }
            } else {
                // 单个水印,居中
                FontMetrics fontMetrics = g2d.getFontMetrics();
                int textWidth = fontMetrics.stringWidth(text);
                int x = (width - textWidth) / 2;
                int y = height / 2;
                g2d.drawString(text, x, y);
            }
            g2d.dispose();
            // 合并图片
            BufferedImage result = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D resultG2d = result.createGraphics();
            resultG2d.drawImage(sourceImage, 0, 0, null);
            // 设置透明度
            AlphaComposite alphaComposite = AlphaComposite.getInstance(
                AlphaComposite.SRC_OVER, alpha);
            resultG2d.setComposite(alphaComposite);
            resultG2d.drawImage(watermarkImage, 0, 0, null);
            resultG2d.dispose();
            ImageIO.write(result, "jpg", new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 添加斜角平铺水印(类似平铺瓷砖效果)
     */
    public static void addTileWatermark(String sourcePath, String targetPath,
                                        String text, Color color, float alpha) {
        try {
            BufferedImage sourceImage = ImageIO.read(new File(sourcePath));
            int width = sourceImage.getWidth();
            int height = sourceImage.getHeight();
            BufferedImage result = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = result.createGraphics();
            g2d.drawImage(sourceImage, 0, 0, null);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            // 创建小块水印
            int tileSize = 150;
            BufferedImage tile = createTextTile(text, tileSize, color);
            for (int x = 0; x < width; x += tileSize) {
                for (int y = 0; y < height; y += tileSize) {
                    g2d.drawImage(tile, x, y, null);
                }
            }
            g2d.dispose();
            ImageIO.write(result, "jpg", new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 创建文字小方块
     */
    private static BufferedImage createTextTile(String text, int size, Color color) {
        BufferedImage tile = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = tile.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setFont(new Font("宋体", Font.PLAIN, 20));
        g2d.setColor(color);
        // 在方块中心绘制文字
        FontMetrics fm = g2d.getFontMetrics();
        int textWidth = fm.stringWidth(text);
        int textHeight = fm.getHeight();
        // 绘制两行文字和简单边框
        g2d.drawString(text, (size - textWidth) / 2, (size - textHeight) / 2);
        g2d.drawRect(5, 5, size - 10, size - 10);
        g2d.dispose();
        return tile;
    }
    /**
     * 批量添加水印
     */
    public static void batchAddWatermark(String sourceDir, String targetDir,
                                         String watermarkText, float alpha) {
        File dir = new File(sourceDir);
        File target = new File(targetDir);
        if (!target.exists()) {
            target.mkdirs();
        }
        File[] files = dir.listFiles((d, name) -> 
            name.endsWith(".jpg") || 
            name.endsWith(".jpeg") || 
            name.endsWith(".png") || 
            name.endsWith(".bmp"));
        if (files != null) {
            for (File file : files) {
                String fileName = file.getName();
                String targetPath = targetDir + File.separator + fileName;
                try {
                    // 添加文字水印
                    addTextWatermarkCenter(file.getAbsolutePath(), targetPath, 
                        watermarkText, alpha);
                    System.out.println("处理完成: " + fileName);
                } catch (Exception e) {
                    System.err.println("处理失败: " + fileName + " - " + e.getMessage());
                }
            }
        }
    }
    private static void addTextWatermarkCenter(String sourcePath, String targetPath,
                                                String text, float alpha) {
        try {
            BufferedImage source = ImageIO.read(new File(sourcePath));
            int width = source.getWidth();
            int height = source.getHeight();
            BufferedImage result = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = result.createGraphics();
            g2d.drawImage(source, 0, 0, null);
            // 半透明水印
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            // 多行文字水印
            g2d.setFont(new Font("微软雅黑", Font.PLAIN, Math.max(20, width / 20)));
            g2d.setColor(Color.WHITE);
            // 居中绘制
            FontMetrics fm = g2d.getFontMetrics();
            int textWidth = fm.stringWidth(text);
            int x = (width - textWidth) / 2;
            int y = height / 2;
            // 添加文字阴影效果
            g2d.setColor(new Color(0, 0, 0, 100));
            g2d.drawString(text, x + 2, y + 2);
            // 主文字
            g2d.setColor(new Color(255, 255, 255, 150));
            g2d.drawString(text, x, y);
            g2d.dispose();
            ImageIO.write(result, "jpg", new File(targetPath));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试类

WatermarkTest.java

import java.awt.*;
/**
 * 水印测试类
 */
public class WatermarkTest {
    public static void main(String[] args) {
        String sourcePath = "D:/test/source.jpg";
        String targetPath = "D:/test/result.jpg";
        String watermarkPath = "D:/test/logo.png";
        // 1. 添加文字水印
        ImageWatermarkUtil.addTextWatermark(
            sourcePath,
            targetPath,
            "© 2024 版权所有",
            Font.BOLD,
            30,
            new Color(255, 255, 0),
            0.5f,
            100,
            100
        );
        // 2. 添加平铺文字水印
        ImageWatermarkUtil.addTextWatermarkTile(
            sourcePath,
            "D:/test/result_tile.jpg",
            "PROTECTED",
            Font.PLAIN,
            20,
            Color.WHITE,
            0.1f
        );
        // 3. 添加图片水印
        ImageWatermarkUtil.addImageWatermark(
            sourcePath,
            watermarkPath,
            "D:/test/result_logo.jpg",
            0.5f,
            50,
            50,
            0.5
        );
        // 4. 添加右下角图片水印
        ImageWatermarkUtil.addImageWatermarkBottomRight(
            sourcePath,
            watermarkPath,
            "D:/test/result_logo_br.jpg",
            0.3f
        );
        // 5. 使用高级功能
        WatermarkService.addRotatedTextWatermark(
            sourcePath,
            "D:/test/result_rotated.jpg",
            "CONFIDENTIAL",
            0.3f,
            true
        );
        // 6. 批量处理
        // WatermarkService.batchAddWatermark(
        //     "D:/test/images",
        //     "D:/test/watermarked",
        //     "SAMPLE",
        //     0.3f
        // );
        System.out.println("所有水印处理完成!");
    }
}

Web应用集成示例

WatermarkController.java (Spring Boot)

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
 * 水印API接口
 */
@RestController
@RequestMapping("/api/watermark")
public class WatermarkController {
    /**
     * 上传图片并添加文字水印
     */
    @PostMapping("/text")
    public ResponseEntity<byte[]> addTextWatermark(
            @RequestParam("file") MultipartFile file,
            @RequestParam("text") String text,
            @RequestParam(value = "alpha", defaultValue = "0.5") float alpha) {
        try {
            // 读取上传的图片
            BufferedImage sourceImage = ImageIO.read(file.getInputStream());
            int width = sourceImage.getWidth();
            int height = sourceImage.getHeight();
            // 创建画布
            BufferedImage result = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = result.createGraphics();
            // 绘制原图
            g2d.drawImage(sourceImage, 0, 0, null);
            // 设置水印
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            g2d.setFont(new Font("微软雅黑", Font.BOLD, Math.max(20, width / 15)));
            // 计算位置(底部居中)
            FontMetrics fm = g2d.getFontMetrics();
            int textWidth = fm.stringWidth(text);
            int x = (width - textWidth) / 2;
            int y = height - 50;
            // 添加阴影效果
            g2d.setColor(new Color(0, 0, 0, 100));
            g2d.drawString(text, x + 2, y + 2);
            // 主文字
            g2d.setColor(Color.WHITE);
            g2d.drawString(text, x, y);
            g2d.dispose();
            // 输出图片
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(result, "jpg", baos);
            return ResponseEntity.ok()
                .header("Content-Type", "image/jpeg")
                .body(baos.toByteArray());
        } catch (IOException e) {
            return ResponseEntity.badRequest().build();
        }
    }
    /**
     * 上传图片并添加图片水印
     */
    @PostMapping("/image")
    public ResponseEntity<byte[]> addImageWatermark(
            @RequestParam("file") MultipartFile file,
            @RequestParam("watermark") MultipartFile watermark,
            @RequestParam(value = "alpha", defaultValue = "0.5") float alpha) {
        try {
            // 读取两张图片
            BufferedImage sourceImage = ImageIO.read(file.getInputStream());
            BufferedImage watermarkImage = ImageIO.read(watermark.getInputStream());
            int width = sourceImage.getWidth();
            int height = sourceImage.getHeight();
            // 创建结果图片
            BufferedImage result = new BufferedImage(width, height, 
                BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = result.createGraphics();
            // 绘制原图
            g2d.drawImage(sourceImage, 0, 0, null);
            // 绘制水印(右下角)
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
            int watermarkWidth = watermarkImage.getWidth();
            int watermarkHeight = watermarkImage.getHeight();
            int x = width - watermarkWidth - 20;
            int y = height - watermarkHeight - 20;
            g2d.drawImage(watermarkImage, x, y, null);
            g2d.dispose();
            // 输出
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(result, "jpg", baos);
            return ResponseEntity.ok()
                .header("Content-Type", "image/jpeg")
                .body(baos.toByteArray());
        } catch (IOException e) {
            return ResponseEntity.badRequest().build();
        }
    }
}

使用说明与注意事项

依赖配置 (pom.xml)

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 图片处理(可选,用于更高级的图片处理) -->
    <dependency>
        <groupId>net.coobird</groupId>
        <artifactId>thumbnailator</artifactId>
        <version>0.4.20</version>
    </dependency>
</dependencies>

注意事项

  1. 性能优化:处理大图片时建议先压缩再加水印
  2. 中文支持:确保系统有对应中文字体
  3. 内存管理:及时释放Graphics对象
  4. 色彩模式:处理PNG透明图片时使用ARGB模式
  5. 文件名处理:避免中文路径导致的编码问题

这些示例代码覆盖了常见的水印使用场景,您可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!