一、添加文字水印
public static void addWatermark(File input, File out, String text, int fontSize) {
// 读取原图片
BufferedImage image = null;
try {
image = ImageIO.read(input);
} catch (IOException e) {
e.printStackTrace();
}
// 获取图片的宽度和高度
int width = image.getWidth();
int height = image.getHeight();
// 创建一个图片缓存对象
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图片的画笔
Graphics2D g = newImage.createGraphics();
// 将原图片绘制到缓存图片上
g.drawImage(image, 0, 0, width, height, null);
// 创建字体对象
Font font = new Font("微软雅黑", Font.BOLD, fontSize);
// 创建字体渲染上下文
FontRenderContext frc = new FontRenderContext(null, true, true);
// 计算字符串的宽度和高度
Rectangle2D bounds = font.getStringBounds(text, frc);
// 字符宽度
int strWidth = (int) bounds.getWidth();
// 字符高度
int strHeight = (int) bounds.getHeight();
// 设置水印的字体样式
g.setFont(font);
// 设置水印的颜色
g.setColor(Color.red);
// 设置水印的位置 根据需要再自行调整宽度、高度
g.drawString(text, width - strWidth - 10, height - strHeight + 15);
// 释放图形上下文使用的系统资源
g.dispose();
// 保存带水印的图片
try {
ImageIO.write(newImage, "png", out);
} catch (IOException e) {
e.printStackTrace();
}
}
二、添加图片水印
public static void addWatermark(File input, File out, File watermarkImage) {
// 读取添加水印的图片
BufferedImage image = null;
try {
image = ImageIO.read(input);
} catch (IOException e) {
e.printStackTrace();
}
// 获取图片的宽度和高度
int width = image.getWidth();
int height = image.getHeight();
// 创建一个图片缓存对象
BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 获取图片的画笔
Graphics2D g = newImage.createGraphics();
// 将原图片绘制到缓存图片上
g.drawImage(image, 0, 0, width, height, null);
// 读取水印图片
BufferedImage watermark = null;
try {
watermark = ImageIO.read(watermarkImage);
} catch (IOException e) {
e.printStackTrace();
}
// 获取水印图片的宽度和高度
int wmWidth = watermark.getWidth();
int wmHeight = watermark.getHeight();
// 设置水印图片的透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.5f));
// 绘制水印图片
g.drawImage(watermark, width - wmWidth - 10, height - wmHeight - 10, wmWidth, wmHeight, null);
// 释放图形上下文使用的系统资源
g.dispose();
// 保存带水印的图片
try {
ImageIO.write(newImage, "png", out);
} catch (IOException e) {
e.printStackTrace();
}
}
三、添加循环水印
水印透明度:
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f);
graphics.setComposite(COMPOSITE);
参数解析
-
rule (混合规则)
- 决定源图像(水印)与目标图像(原图)如何混合
- 常见规则包括:
SRC_OVER
:水印覆盖在原图上方(最常用)SRC_IN
:只显示水印与原图重叠且原图不透明的部分SRC_ATOP
:水印覆盖在原图上,但只显示原图范围内的水印XOR
:异或模式,重叠部分会变透明
-
alpha (透明度值)
- 取值范围 [0.0, 1.0]
- 控制水印的透明度:
- 0.0 表示完全透明(不可见)
- 0.5 表示半透明
- 1.0 表示完全不透明
public class ImageUtils {
// 水印字体
private static final Font FONT = new Font("微软雅黑", Font.PLAIN, 24);
// 透明度
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
// 水印之间的间隔
private static final int X_MOVE = 150;
// 水印之间的间隔
private static final int Y_MOVE = 180;
public static void markWithDefContent(String imgPath, String waterMarkContent){
try {
markWithContent(imgPath, FONT, Color.darkGray, waterMarkContent, imgPath);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void markWithContent(String inputImgPath, Font font, Color markContentColor,
String waterMarkContent,
String outImgPath) throws IOException {
// 读取原图片信息
File srcFile = new File(inputImgPath);
File outFile = new File(outImgPath);
BufferedImage srcImg = ImageIO.read(srcFile);
// 图片宽、高
int imgWidth = srcImg.getWidth();
int imgHeight = srcImg.getHeight();
// 图片缓存
BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 创建绘图工具
Graphics2D graphics = bufImg.createGraphics();
// 画入原始图像
graphics.drawImage(srcImg, 0, 0, imgWidth, imgHeight, null);
// 设置水印颜色
graphics.setColor(markContentColor);
// 设置水印透明度
graphics.setComposite(COMPOSITE);
// 设置倾斜角度
graphics.rotate(Math.toRadians(-35), (double) bufImg.getWidth() / 2,
(double) bufImg.getHeight() / 2);
// 设置水印字体
graphics.setFont(font);
// 消除java.awt.Font字体的锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int xCoordinate = -imgWidth / 2, yCoordinate;
// 字体长度
int markWidth = FONT.getSize() * getTextLength(waterMarkContent);
// 字体高度
int markHeight = FONT.getSize();
// 循环添加水印
while (xCoordinate < imgWidth * 1.5) {
yCoordinate = -imgHeight / 2;
while (yCoordinate < imgHeight * 1.5) {
graphics.drawString(waterMarkContent, xCoordinate, yCoordinate);
yCoordinate += markHeight + Y_MOVE;
}
xCoordinate += markWidth + X_MOVE;
}
// 释放画图工具
graphics.dispose();
try (FileOutputStream fos = new FileOutputStream(outFile)) {
// 输出图片
ImageIO.write(bufImg, "jpg", fos);
fos.flush();
}
}
/**
* 计算水印文本长度
* 中文长度即文本长度
* 英文长度为文本长度二分之一
*/
public static int getTextLength(String text) {
//水印文字长度
int length = text.length();
for (int i = 0; i < text.length(); i++) {
String s = String.valueOf(text.charAt(i));
if (s.getBytes().length > 1) {
length++;
}
}
length = length % 2 == 0 ? length / 2 : length / 2 + 1;
return length;
}
public static void main(String[] args) throws IOException {
// 输入图片路径
String inputFile = "D:\\data\\szjd\\server\\upload\\test.png";
// 输出图片路径
String outputFile = "D:\\data\\szjd\\server\\upload\\test1.png";
// 水印文本内容,中文转Unicode
String watermarkText = "111喝喝123qwe";
ImageUtils.markWithContent(inputFile, FONT, Color.darkGray, watermarkText, outputFile);
}