文章目录
- 前言
- 一、工具类WatermarkUtil
- 二、工具类介绍
- 2.1 图片来源类型
- 2.2 水印类型
- 2.3 读取本地图片
- 2.4 读取网络图片
- 2.5 水印处理
- 2.6 添加水印
- 三、测试添加水印
- 总结
前言
给图片添加水印是一个很常见的需求,一般是用来防盗用。比如我们csdn上面写的文章中,如果包含图片,那么可以给图片带上个人水印标志。笔者是因为工作需要,特此研究一下使用java实现给图片加水印的方法。
一、工具类WatermarkUtil
完整的工具类代码如下
package com.hulei.watermark;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
/**
* 添加水印util
*/
public class WatermarkUtil {
/**
* 添加水印
*
* @param pictureSourceType 图片来源类型
* @param watermarkType 水印类型
* @param path 图片路径
* @param watermark 水印内容(文字水印内容/图片水印的存放路径)
* @param formatName 图片格式
* @param targetPath 输出图片存放路径
* @param color 水印颜色
*/
public static void addWatermark(PictureSourceType pictureSourceType, WatermarkType watermarkType, String path, String watermark, String formatName, String targetPath, Color color) {
if (null == pictureSourceType) {
throw new RuntimeException("图片来源类型不能为空");
}
if (null == watermarkType) {
throw new RuntimeException("水印类型不能为空");
}
Image image;
if (pictureSourceType == PictureSourceType.LOCAL_PICTURE) {
// 读取本地图片
image = readLocalPicture(path);
} else {
// 读取网络图片
image = readNetworkPicture(path);
}
// 水印处理
manageWatermark(image, watermarkType, watermark, formatName, targetPath, color);
}
//图片来源类型枚举
public enum PictureSourceType {
//本地图片
LOCAL_PICTURE,
//网络图片
NETWORK_PICTURE;
}
//水印类型枚举
public enum WatermarkType {
//文字水印
TEXT_WATERMARK,
//图片水印
IMAGE_WATERMARK;
}
/**
* 读取本地图片
*
* @param path 本地图片存放路径
*/
public static Image readLocalPicture(String path) {
if (null == path) {
throw new RuntimeException("本地图片路径不能为空");
}
// 读取原图片信息 得到文件
File srcImgFile = new File(path);
try {
// 将文件对象转化为图片对象
return ImageIO.read(srcImgFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 读取网络图片
*
* @param path 网络图片地址
*/
public static Image readNetworkPicture(String path) {
if (null == path) {
throw new RuntimeException("网络图片路径不能为空");
}
try {
// 创建一个URL对象,获取网络图片的地址信息
URL url = new URL(path);
// 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
BufferedImage bugImg = ImageIO.read(url.openStream());
if (null == bugImg) {
throw new RuntimeException("网络图片地址不正确");
}
return bugImg;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 水印处理
*
* @param image 图片对象
* @param watermarkType 水印类型(1-文字水印 2-图片水印)
* @param watermark 水印内容(文字水印内容/图片水印的存放路径)
* @param formatName 图片格式
* @param tarImgPath 输出图片存放路径
* @param color 水印颜色
*/
public static void manageWatermark(Image image, WatermarkType watermarkType, String watermark, String formatName, String tarImgPath, Color color) {
int imgWidth = image.getWidth(null);
int imgHeight = image.getHeight(null);
BufferedImage bufImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 加水印,创建画笔
Graphics2D graphics = bufImg.createGraphics();
// 绘制原始图片
graphics.drawImage(image, 0, 0, imgWidth, imgHeight, null);
// 校验水印的类型
if (watermarkType == WatermarkType.TEXT_WATERMARK) {
if (watermark.isEmpty()) {
throw new RuntimeException("文字水印内容不能为空");
}
// 添加文字水印:
// 根据图片的背景设置水印颜色
graphics.setColor(color == null ? Color.RED : color);
// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小为45pt
graphics.setFont(new Font("微软雅黑", Font.BOLD, 45));
// 设置水印的坐标(为原图片中间位置)
int x = (imgWidth - getWatermarkLength(watermark, graphics)) / 2;
int y = imgHeight / 2;
// 画出水印 第一个参数是水印内容,第二个参数是x轴坐标,第三个参数是y轴坐标
graphics.drawString(watermark, x, y);
graphics.dispose();
} else {
// 添加图片水印:
if (watermark.isEmpty()) {
throw new RuntimeException("图片水印存放路径不能为空");
}
Image srcWatermark = readLocalPicture(watermark);
int watermarkWidth = srcWatermark.getWidth(null);
int watermarkHeight = srcWatermark.getHeight(null);
// 设置 alpha 透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));
// 绘制水印图片 坐标为中间位置
graphics.drawImage(srcWatermark, (imgWidth - watermarkWidth) / 2, (imgHeight - watermarkHeight) / 2, watermarkWidth, watermarkHeight, null);
graphics.dispose();
}
// 输出图片
try {
FileOutputStream outImgStream = new FileOutputStream(tarImgPath);
ImageIO.write(bufImg, formatName, outImgStream);
outImgStream.flush();
outImgStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 获取水印文字的长度
*
* @param watermarkContent 文字水印内容
* @param graphics 图像类
*/
private static int getWatermarkLength(String watermarkContent, Graphics2D graphics) {
return graphics.getFontMetrics(graphics.getFont()).charsWidth(watermarkContent.toCharArray(), 0, watermarkContent.length());
}
}
二、工具类介绍
2.1 图片来源类型
这个枚举主要包括两个待添加水印的图片来源类型,分别为本地图片和网络图片,即是给本地图片加水印还是网络图片加水印。
//图片来源类型枚举
public enum PictureSourceType {
//本地图片
LOCAL_PICTURE,
//网络图片
NETWORK_PICTURE;
}
2.2 水印类型
给图片加水印,水印也分为两种类型,分别为文字水印和图片水印,图片水印即是把图片作为水印添加到另外一个图片上。
//水印类型枚举
public enum WatermarkType {
//文字水印
TEXT_WATERMARK,
//图片水印
IMAGE_WATERMARK;
}
2.3 读取本地图片
该函数用于读取指定路径下的本地图片,并返回一个Image对象。如果路径为空,则抛出运行时异常;如果读取图片失败,则将捕获的IOException转换为运行时异常抛出。
2.4 读取网络图片
该函数用于读取网络图片。首先检查传入的网络图片地址是否为空,如果为空则抛出运行时异常。然后通过URL对象获取网络图片的输入流,并使用ImageIO的read方法将输入流转化为图片对象。如果转化失败则抛出运行时异常。最后返回转化成功的图片对象。
2.5 水印处理
该函数用于给图片添加水印,支持文字水印和图片水印两种类型。根据传入的水印类型,选择添加文字水印或图片水印。对于文字水印,会根据传入的颜色设置水印颜色,设置字体样式为微软雅黑加粗45pt,将水印内容居中显示在图片上。对于图片水印,会读取指定路径的图片,并将其居中显示在图片上。最后将添加了水印的图片输出到指定路径。
2.6 添加水印
该函数用于给图片添加水印。根据传入的图片来源类型和水印类型,读取相应的图片并进行水印处理,最后将处理后的图片保存到指定路径。具体流程如下:
- 检查传入的图片来源类型和水印类型是否为空,若为空则抛出异常。
- 根据图片来源类型,读取本地图片或网络图片。
- 调用manageWatermark方法对图片进行水印处理,处理包括水印类型、水印内容、图片格式、输出路径和水印颜色等参数。
- 完成水印处理后,函数执行结束。
public static void addWatermark(PictureSourceType pictureSourceType, WatermarkType watermarkType, String path, String watermark, String formatName, String targetPath, Color color) {
if (null == pictureSourceType) {
throw new RuntimeException("图片来源类型不能为空");
}
if (null == watermarkType) {
throw new RuntimeException("水印类型不能为空");
}
Image image;
if (pictureSourceType == PictureSourceType.LOCAL_PICTURE) {
// 读取本地图片
image = readLocalPicture(path);
} else {
// 读取网络图片
image = readNetworkPicture(path);
}
// 水印处理
manageWatermark(image, watermarkType, watermark, formatName, targetPath, color);
}
三、测试添加水印
主要功能是给图片添加水印。具体来说,函数使用了WatermarkUtil工具类的addWatermark方法,实现了给本地图片和网络图片添加文字水印和图片水印,并将添加水印后的图片保存到指定路径。函数中定义了图片的本地路径、网络地址、水印内容、水印图片路径、输出格式以及水印颜色等参数。通过调用addWatermark方法,实现了给本地图片和网络图片添加文字水印和图片水印的功能。
测试类完整代码
package com.hulei.watermark;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.awt.*;
@SpringBootTest
class AddWaterMarkApplicationTests {
@Test
void contextLoads() {
// 本地图片路径
String localPath = "D:/localImage.png";
// 网络图片地址
String networkPath = "https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2023%2F0329%2F31dc71faj00rs8saz004sd000vc015sm.jpg&thumbnail=660x2147483647&quality=80&type=jpg";
// 文字水印内容
String textWatermark = "Hello World!";
// 图片水印路径
String pictureWatermark = "D:/imageWaterMark.png";
//输出图片的格式
String outputFormat = "jpg";
//本地图片添加文字水印输出地址
String local_image_text_watermark = "E:/local_image_text_watermark.jpg";
//本地图片添加图片水印输出地址
String local_image_picture_watermark = "E:/local_image_picture_watermark.jpg";
//网络图片添加文字水印输出地址
String network_image_text_watermark = "E:/network_image_text_watermark.jpg";
//网络图片添加图片水印输出地址
String network_image_picture_watermark = "E:/network_image_picture_watermark.jpg";
// 本地图片 添加文字水印
WatermarkUtil.addWatermark(WatermarkUtil.PictureSourceType.LOCAL_PICTURE, WatermarkUtil.WatermarkType.TEXT_WATERMARK, localPath,textWatermark,outputFormat,local_image_text_watermark,Color.RED);
// 本地图片 添加图片水印,图片水印不需要设置颜色
WatermarkUtil.addWatermark(WatermarkUtil.PictureSourceType.LOCAL_PICTURE, WatermarkUtil.WatermarkType.IMAGE_WATERMARK, localPath, pictureWatermark,outputFormat,local_image_picture_watermark,null);
// 网络图片 添加文字水印
WatermarkUtil.addWatermark(WatermarkUtil.PictureSourceType.NETWORK_PICTURE, WatermarkUtil.WatermarkType.TEXT_WATERMARK, networkPath, textWatermark,outputFormat,network_image_text_watermark,Color.RED);
// 网络图片 添加图片水印,图片水印不需要设置颜色
WatermarkUtil.addWatermark(WatermarkUtil.PictureSourceType.NETWORK_PICTURE, WatermarkUtil.WatermarkType.IMAGE_WATERMARK, networkPath, pictureWatermark,outputFormat,network_image_picture_watermark,null);
}
}
注意:png图片不能是非png格式的图片通过改名和修改后缀得到,否则将会读取不到图片
这两个图片分别为本地图片和作为水印的图片,笔者放在了D盘根目录下
点击测试类方法后会在E盘得到四张不同图片,依次如下:
- 本地图片添加文字水印
- 本地图片添加图片水印
- 网络图片添加文字水印
- 网络图片添加图片水印
总结
以上就是笔者在探索使用java为图片添加水印完整过程,使用的都是java原生提供的处理图片的方式。使用的图片都是一些网上随便找的,如有侵权请评论区找我,我会及时撤下哈。