本文目录导读:

我来为您提供一个完整的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>
注意事项
- 性能优化:处理大图片时建议先压缩再加水印
- 中文支持:确保系统有对应中文字体
- 内存管理:及时释放Graphics对象
- 色彩模式:处理PNG透明图片时使用ARGB模式
- 文件名处理:避免中文路径导致的编码问题
这些示例代码覆盖了常见的水印使用场景,您可以根据实际需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播