Java案例如何实现水印?

wen python案例 2

本文目录导读:

Java案例如何实现水印?

  1. 使用Java标准库(Graphics2D)
  2. 使用Thumbnailator库(推荐)
  3. 使用Apache PDFBox(处理PDF水印)
  4. 专业方案:全图平铺水印
  5. 性能优化建议
  6. 选择建议

Java实现水印的常见方案有以下几种,我将按照从简单到专业的顺序为你介绍:

使用Java标准库(Graphics2D)

这是最基础的实现方式,无需额外依赖:

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class WatermarkUtil {
    /**
     * 添加文字水印
     */
    public static void addTextWatermark(String sourcePath, String outputPath, 
                                       String watermarkText, Color color, float alpha) throws IOException {
        // 读取原图
        BufferedImage image = ImageIO.read(new File(sourcePath));
        // 创建Graphics2D对象
        Graphics2D g2d = (Graphics2D) image.getGraphics();
        // 设置抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 设置透明度
        AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
        g2d.setComposite(alphaComposite);
        // 设置文字颜色和字体
        g2d.setColor(color);
        g2d.setFont(new Font("微软雅黑", Font.BOLD, 60));
        // 获取文字尺寸
        FontMetrics fontMetrics = g2d.getFontMetrics();
        int textWidth = fontMetrics.stringWidth(watermarkText);
        int textHeight = fontMetrics.getHeight();
        // 计算中心位置
        int x = (image.getWidth() - textWidth) / 2;
        int y = (image.getHeight() - textHeight) / 2;
        // 绘制水印
        g2d.drawString(watermarkText, x, y);
        g2d.dispose();
        // 输出图片
        ImageIO.write(image, "png", new File(outputPath));
    }
    /**
     * 添加图片水印
     */
    public static void addImageWatermark(String sourcePath, String watermarkPath, 
                                        String outputPath, float alpha) throws IOException {
        BufferedImage image = ImageIO.read(new File(sourcePath));
        BufferedImage watermark = ImageIO.read(new File(watermarkPath));
        Graphics2D g2d = (Graphics2D) image.getGraphics();
        // 设置透明度
        AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha);
        g2d.setComposite(alphaComposite);
        // 绘制水印(右下角)
        int x = image.getWidth() - watermark.getWidth() - 20;
        int y = image.getHeight() - watermark.getHeight() - 20;
        g2d.drawImage(watermark, x, y, null);
        g2d.dispose();
        ImageIO.write(image, "png", new File(outputPath));
    }
    public static void main(String[] args) {
        try {
            // 文字水印示例
            addTextWatermark("input.jpg", "output.png", 
                           "保密文件", Color.GRAY, 0.5f);
            // 图片水印示例
            addImageWatermark("input.jpg", "logo.png", 
                            "output.png", 0.3f);
            System.out.println("水印添加成功!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用Thumbnailator库(推荐)

Thumbnailator是一个优秀的图片处理库,简化了图片操作:

<!-- Maven依赖 -->
<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.20</version>
</dependency>
import net.coobird.thumbnailator.Thumbnails;
import net.coobird.thumbnailator.geometry.Positions;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ThumbnailatorWatermark {
    /**
     * 添加图片水印
     */
    public static void addWatermark(String sourcePath, String watermarkPath, 
                                    String outputPath, float quality) throws IOException {
        Thumbnails.of(sourcePath)
                .size(800, 600)  // 可以调整尺寸
                .watermark(Positions.BOTTOM_RIGHT, 
                          ImageIO.read(new File(watermarkPath)), 0.5f)
                .outputQuality(quality)
                .toFile(outputPath);
    }
    /**
     * 添加文字水印(需要先创建文字图片)
     */
    public static void addTextWatermark(String sourcePath, String text, 
                                       String outputPath) throws IOException {
        // 创建文字水印图片
        BufferedImage watermark = new BufferedImage(200, 50, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = watermark.createGraphics();
        g2d.setColor(Color.GRAY);
        g2d.setFont(new Font("Arial", Font.BOLD, 20));
        g2d.drawString(text, 10, 30);
        g2d.dispose();
        // 应用水印
        Thumbnails.of(sourcePath)
                .size(800, 600)
                .watermark(Positions.CENTER, watermark, 0.5f)
                .toFile(outputPath);
    }
}

使用Apache PDFBox(处理PDF水印)

如果需要给PDF添加水印:

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.27</version>
</dependency>
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import java.io.File;
import java.io.IOException;
public class PDFWatermark {
    public static void addWatermark(String sourcePath, String outputPath, 
                                   String text) throws IOException {
        try (PDDocument document = PDDocument.load(new File(sourcePath))) {
            // 加载字体
            PDType0Font font = PDType0Font.load(document, 
                new File("path/to/simhei.ttf")); // 需要中文字体
            PDExtendedGraphicsState gs = new PDExtendedGraphicsState();
            gs.setNonStrokingAlphaConstant(0.3f); // 透明度
            for (PDPage page : document.getPages()) {
                try (PDPageContentStream cs = new PDPageContentStream(
                        document, page, 
                        PDPageContentStream.AppendMode.APPEND, true)) {
                    cs.setGraphicsStateParameters(gs);
                    cs.setNonStrokingColor(200, 200, 200); // 浅灰色
                    cs.setFont(font, 60);
                    // 旋转45度添加水印
                    cs.transformTextMatrix(
                        new org.apache.pdfbox.util.Matrix(
                            0.707f, -0.707f, 0.707f, 0.707f, 200, 400));
                    cs.showText(text);
                }
            }
            document.save(outputPath);
        }
    }
}

专业方案:全图平铺水印

创建覆盖全图的平铺水印效果:

public static BufferedImage addTileWatermark(BufferedImage source, 
                                             String text, float alpha) {
    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.rotate(Math.toRadians(-45), width / 2, height / 2);
    // 设置文字属性
    g2d.setColor(Color.LIGHT_GRAY);
    g2d.setFont(new Font("微软雅黑", Font.PLAIN, 30));
    // 平铺水印
    FontMetrics fm = g2d.getFontMetrics();
    int textWidth = fm.stringWidth(text);
    int textHeight = fm.getHeight();
    int spacing = 200; // 间距
    for (int x = -width; x < width * 2; x += spacing + textWidth) {
        for (int y = -height; y < height * 2; y += spacing + textHeight) {
            g2d.drawString(text, x, y);
        }
    }
    g2d.dispose();
    return result;
}

性能优化建议

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BatchWatermarkProcessor {
    private static final ExecutorService executor = Executors.newFixedThreadPool(4);
    public void batchProcess(List<String> filePaths) {
        for (String path : filePaths) {
            executor.submit(() -> {
                try {
                    // 处理单个图片
                    processImage(path);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }
    private void processImage(String path) throws IOException {
        // 复用BufferedImage对象
        BufferedImage image = ImageIO.read(new File(path));
        // ... 添加水印逻辑
    }
}

选择建议

  1. 简单需求:使用Graphics2D标准库
  2. 图片处理:推荐Thumbnailator,API简洁
  3. PDF处理:使用PDFBox
  4. 企业级应用:考虑使用ImageMagick(通过JMagick或im4java库)
  5. 性能要求:使用线程池批量处理,考虑图片缓存

注意:处理中文字体时,确保系统安装了相应的中文字体,或使用字体文件加载。

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