本文目录导读:

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));
// ... 添加水印逻辑
}
}
选择建议
- 简单需求:使用Graphics2D标准库
- 图片处理:推荐Thumbnailator,API简洁
- PDF处理:使用PDFBox
- 企业级应用:考虑使用ImageMagick(通过JMagick或im4java库)
- 性能要求:使用线程池批量处理,考虑图片缓存
注意:处理中文字体时,确保系统安装了相应的中文字体,或使用字体文件加载。