2025/06/05日日志 使用 Java 为图片添加各种样式的水印

使用 Java 为图片添加各种样式的水印

1. 水印的基本原理

无论是文本水印还是图像水印,其核心都是将水印内容绘制在目标图像上。Java 提供了强大的 Graphics2D 类,可以用来在图像上绘制各种图形和文本。以下是实现水印的关键点:

1.1 Graphics2D 简介

Graphics2Djava.awt.Graphics 类的子类,提供了更强大的图形处理能力,支持复杂的图形操作,如旋转、缩放、变换和抗锯齿等。在添加水印时,我们将使用 Graphics2D 对象来绘制水印。

1.2 AlphaComposite 控制透明度

在为图片添加水印时,通常需要控制水印的透明度,使其不会完全遮盖住原图。Java 中的 AlphaComposite 类允许我们通过设置透明度来混合图像和水印。

1.3 水印的位置与布局

水印的位置是指在目标图像上的具体绘制位置。水印可以放置在图像的任意位置,如左上角、右下角或中心等。我们可以通过控制 Graphics2D 对象的绘制坐标来实现水印的位置调整。

2. 实现文本水印

文本水印是最简单的一种水印形式,通常用于在图像上添加文字信息,如作者名、版权声明或其他标识。

2.1 添加简单的文本水印

以下是一个简单的代码示例,展示了如何在图像的右下角添加一段文本作为水印:

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class TextWatermark {

    public static void addTextWatermark(String text, File sourceImageFile, File destImageFile) {
        try {
            BufferedImage sourceImage = ImageIO.read(sourceImageFile);
            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
            g2d.setComposite(alphaChannel);
            g2d.setColor(Color.GRAY);
            g2d.setFont(new Font("Arial", Font.BOLD, 64));

            int x = sourceImage.getWidth() - 100;
            int y = sourceImage.getHeight() - 50;

            g2d.drawString(text, x, y);

            ImageIO.write(sourceImage, "png", destImageFile);
            g2d.dispose();

            System.out.println("Text watermark added successfully.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        File sourceImageFile = new File("src/main/resources/source-image.jpg");
        File destImageFile = new File("src/main/resources/watermarked-image.jpg");
        String watermarkText = "© 2024 MyCompany";

        addTextWatermark(watermarkText, sourceImageFile, destImageFile);
    }
}

2.2 自定义水印位置

我们可以通过传入 xy 参数,灵活地控制水印文本的位置:

public static void addTextWatermark(String text, File sourceImageFile, File destImageFile, int x, int y) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
        g2d.setComposite(alphaChannel);
        g2d.setColor(Color.GRAY);
        g2d.setFont(new Font("Arial", Font.BOLD, 64));

        g2d.drawString(text, x, y);

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Text watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

2.3 自定义水印样式

我们还可以通过调整字体、颜色和透明度等参数来自定义水印的样式:

public static void addStyledTextWatermark(String text, File sourceImageFile, File destImageFile) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
        g2d.setComposite(alphaChannel);
        g2d.setColor(Color.BLUE);
        g2d.setFont(new Font("Courier New", Font.ITALIC, 80));

        int x = 20;
        int y = 100;
        g2d.drawString(text, x, y);

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Styled text watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

3. 实现图像水印

图像水印通常用于添加公司 Logo 或品牌标识。实现图像水印的步骤与文本水印类似,只是将 drawString 替换为 drawImage

3.1 添加简单的图像水印

以下是一个将 Logo 作为水印添加到目标图像的示例:

public static void addImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);

        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
        g2d.setComposite(alphaChannel);

        int x = sourceImage.getWidth() - watermarkImage.getWidth() - 10;
        int y = sourceImage.getHeight() - watermarkImage.getHeight() - 10;

        g2d.drawImage(watermarkImage, x, y, null);

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Image watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

3.2 自定义图像水印大小

有时,水印图像的尺寸可能与目标图像不匹配。我们可以对水印图像进行缩放,使其适应目标图像的大小:

public static void addScaledImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);

        int scaledWidth = sourceImage.getWidth() / 5;
        int scaledHeight = watermarkImage.getHeight() * scaledWidth / watermarkImage.getWidth();
        Image scaledWatermark = watermarkImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_SMOOTH);

        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
        g2d.setComposite(alphaChannel);

        int x = sourceImage.getWidth() - scaledWidth - 10;
        int y = sourceImage.getHeight() - scaledHeight - 10;

        g2d.drawImage(scaledWatermark, x, y, null);

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Scaled image watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

4. 实现平铺水印

平铺水印是一种将水印重复覆盖整个图像的技术,以增加图像的保护难度。平铺水印可以是文本,也可以是图像。

4.1 平铺文本水印

以下是一个平铺文本水印的实现:

public static void addTiledTextWatermark(String text, File sourceImageFile, File destImageFile) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f);
        g2d.setComposite(alphaChannel);
        g2d.setColor(Color.LIGHT_GRAY);
        g2d.setFont(new Font("Arial", Font.BOLD, 40));

        FontMetrics fontMetrics = g2d.getFontMetrics();
        int textWidth = fontMetrics.stringWidth(text);
        int textHeight = fontMetrics.getHeight();

        for (int x = 0; x < sourceImage.getWidth(); x += textWidth + 20) {
            for (int y = textHeight; y < sourceImage.getHeight(); y += textHeight + 20) {
                g2d.drawString(text, x, y);
            }
        }

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Tiled text watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

4.2 平铺图像水印

以下是一个平铺图像水印的实现:

public static void addTiledImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile) {
    try {
        BufferedImage sourceImage = ImageIO.read(sourceImageFile);
        BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);

        Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

        AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
        g2d.setComposite(alphaChannel);

        for (int x = 0; x < sourceImage.getWidth(); x += watermarkImage.getWidth() + 20) {
            for (int y = 0; y < sourceImage.getHeight(); y += watermarkImage.getHeight() + 20) {
                g2d.drawImage(watermarkImage, x, y, null);
            }
        }

        ImageIO.write(sourceImage, "png", destImageFile);
        g2d.dispose();

        System.out.println("Tiled image watermark added successfully.");
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

5. 综合示例:创建一个水印工具类

为了便于重复使用,我们可以将上述不同类型的水印方法封装到一个工具类中。这样可以更方便地在不同项目中应用水印功能:

public class WatermarkUtils {

    public static void addTextWatermark(String text, File sourceImageFile, File destImageFile, float opacity, Color color, Font font, int x, int y) {
        try {
            BufferedImage sourceImage = ImageIO.read(sourceImageFile);
            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
            g2d.setComposite(alphaChannel);
            g2d.setColor(color);
            g2d.setFont(font);

            g2d.drawString(text, x, y);

            ImageIO.write(sourceImage, "png", destImageFile);
            g2d.dispose();

            System.out.println("Text watermark added successfully.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void addImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile, float opacity, int x, int y) {
        try {
            BufferedImage sourceImage = ImageIO.read(sourceImageFile);
            BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);

            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
            g2d.setComposite(alphaChannel);

            g2d.drawImage(watermarkImage, x, y, null);

            ImageIO.write(sourceImage, "png", destImageFile);
            g2d.dispose();

            System.out.println("Image watermark added successfully.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void addTiledTextWatermark(String text, File sourceImageFile, File destImageFile, float opacity, Color color, Font font, int xStep, int yStep) {
        try {
            BufferedImage sourceImage = ImageIO.read(sourceImageFile);
            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();

            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
            g2d.setComposite(alphaChannel);
            g2d.setColor(color);
            g2d.setFont(font);

            FontMetrics fontMetrics = g2d.getFontMetrics();
            int textWidth = fontMetrics.stringWidth(text);
            int textHeight = fontMetrics.getHeight();

            for (int x = 0; x < sourceImage.getWidth(); x += textWidth + xStep) {
                for (int y = textHeight; y < sourceImage.getHeight(); y += textHeight + yStep) {
                    g2d.drawString(text, x, y);
                }
            }

            ImageIO.write(sourceImage, "png", destImageFile);
            g2d.dispose();

            System.out.println("Tiled text watermark added successfully.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void addTiledImageWatermark(File watermarkImageFile, File sourceImageFile, File destImageFile, float opacity, int xStep, int yStep) {
        try {
            BufferedImage sourceImage = ImageIO.read(sourceImageFile);
            BufferedImage watermarkImage = ImageIO.read(watermarkImageFile);

            Graphics2D g2d = (Graphics2D) sourceImage.getGraphics();
            AlphaComposite alphaChannel = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity);
            g2d.setComposite(alphaChannel);

            for (int x = 0; x < sourceImage.getWidth(); x += watermarkImage.getWidth() + xStep) {
                for (int y = 0; y < sourceImage.getHeight(); y += watermarkImage.getHeight() + yStep) {
                    g2d.drawImage(watermarkImage, x, y, null);
                }
            }

            ImageIO.write(sourceImage, "png", destImageFile);
            g2d.dispose();

            System.out.println("Tiled image watermark added successfully.");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

通过以上示例代码,可以轻松实现 Java 图像处理中的水印功能。

posted @ 2025-06-11 19:22  Moonbeamsc  阅读(314)  评论(0)    收藏  举报
返回顶端