一、话不多说,直接上代码
1.1,水印类型枚举
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @author: wangjing* @createTime: 2023-12-05 15:01* @version: 1.0.0* @Description: 水印类型枚举*/
@Getter
@AllArgsConstructor
@SuppressWarnings("AlibabaEnumConstantsMustHaveComment")
public enum WatermarkTypeEnum {TEXT_WATERMARK(1, "文字水印"),IMAGE_WATERMARK(2, "图片水印");private final Integer code;private final String msg;public static WatermarkTypeEnum matchCode(Integer code) {for (WatermarkTypeEnum watermarkTypeEnum : WatermarkTypeEnum.values()) {if (code.equals(watermarkTypeEnum.getCode())) {return watermarkTypeEnum;}}return null;}}
1.2,图片水印位置类型枚举
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @author: wangjing* @createTime: 2023-12-05 15:01* @version: 1.0.0* @Description: 图片水印位置类型枚举*/
@Getter
@AllArgsConstructor
@SuppressWarnings("AlibabaEnumConstantsMustHaveComment")
public enum ImageWatermarkPositionTypeEnum {/*** 九方位*/CENTER(1, "居中"),LEFT_SIDE(2, "左侧"),RIGHT_SIDE(3, "右侧"),DIRECTLY_ABOVE(4, "正上方"),DIRECTLY_BELOW(5, "正下方"),UPPER_LEFT(6, "左上角"),LOWER_LEFT(7, "左下角"),UPPER_RIGHT(8, "右上方"),LOWER_RIGHT(9, "右下方"),/*** 平铺*/TILE(10, "平铺水印"),TILT_TILE(11, "倾斜平铺");private final Integer code;private final String msg;public static ImageWatermarkPositionTypeEnum matchCode(Integer code) {for (ImageWatermarkPositionTypeEnum imageWatermarkPositionTypeEnum : ImageWatermarkPositionTypeEnum.values()) {if (code.equals(imageWatermarkPositionTypeEnum.getCode())) {return imageWatermarkPositionTypeEnum;}}return null;}}
1.3,图片水印处理类
import cn.piesat.space.watermark.enums.ImageWatermarkPositionTypeEnum;
import cn.piesat.space.watermark.enums.WatermarkTypeEnum;
import lombok.Data;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;/*** @author: wangjing* @createTime: 2023-12-05 15:01* @version: 1.0.0* @Description: 图片水印处理类*/
public class ImageWatermarkUtil {/*** 水印信息对象*/@Datastatic class WatermarkInfo {BufferedImage watermarkBufferedImage;Integer watermarkWidth;Integer watermarkHeight;}/*** 获取水印信息并对画布做基础配置** @param graphics* @param watermarkType* @param watermark* @param font* @param color* @return*/public static WatermarkInfo getWatermarkInfo(Graphics2D graphics, Integer watermarkType, String watermark,Font font, Color color) {WatermarkInfo watermarkInfo = new WatermarkInfo();// 文字水印if (WatermarkTypeEnum.TEXT_WATERMARK.getCode().equals(watermarkType)) {// 设置字体graphics.setFont(font);// 设置颜色graphics.setColor(color);watermarkInfo.setWatermarkWidth(getWatermarkLength(watermark, graphics));watermarkInfo.setWatermarkHeight(font.getSize());} else {// 图片水印BufferedImage对象BufferedImage watermarkBufferedImage = readPicture(watermark);watermarkInfo.setWatermarkBufferedImage(watermarkBufferedImage);watermarkInfo.setWatermarkWidth(watermarkBufferedImage.getWidth());watermarkInfo.setWatermarkHeight(watermarkBufferedImage.getHeight());}return watermarkInfo;}/*** 添加水印** @param bufferedImage 源文件* @param font 字体* @param color 颜色* @param watermarkType 水印类型(具体见 WatermarkTypeEnum 枚举类)* @param imageWatermarkPositionType 水印位置(具体见 ImageWatermarkPositionType)* @param watermark 水印(文字或图片地址)* @return*/public static BufferedImage addWatermark(BufferedImage bufferedImage, Font font, Color color, Integer watermarkType,Integer imageWatermarkPositionType, String watermark) {// 图片宽度Integer imageWidth = bufferedImage.getWidth();// 图片高度Integer imageHeight = bufferedImage.getHeight();// 创建画笔Graphics2D graphics = bufferedImage.createGraphics();WatermarkInfo watermarkInfo = getWatermarkInfo(graphics, watermarkType, watermark, font, color);switch (ImageWatermarkPositionTypeEnum.matchCode(imageWatermarkPositionType)) {// 居中case CENTER:centerCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;// 左侧case LEFT_SIDE:leftSideCompute(graphics, imageHeight, watermarkInfo, watermarkType, watermark);break;// 右侧case RIGHT_SIDE:rightSideCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;// 正上方case DIRECTLY_ABOVE:directlyAboveCompute(graphics, imageWidth, watermarkInfo, watermarkType, watermark);break;// 正下方case DIRECTLY_BELOW:directlyBelowCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;// 左上角case UPPER_LEFT:upperLeftCompute(graphics, watermarkInfo, watermarkType, watermark);break;// 左下角case LOWER_LEFT:lowerLeftCompute(graphics, imageHeight, watermarkInfo, watermarkType, watermark);break;// 右上角case UPPER_RIGHT:upperRightCompute(graphics, imageWidth, watermarkInfo, watermarkType, watermark);break;// 右下角case LOWER_RIGHT:lowerRightCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;// 右下角case TILE:tileDrawCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;// 右下角case TILT_TILE:// 倾斜度graphics.rotate(0.2);tileDrawCompute(graphics, imageWidth, imageHeight, watermarkInfo, watermarkType, watermark);break;default: // 错误的操作类型throw new RuntimeException("错误的操作类型");}graphics.dispose();return bufferedImage;}/*** 居中 配置** @param graphics* @param imageWidth* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void centerCompute(Graphics2D graphics, Integer imageWidth, Integer imageHeight,WatermarkInfo watermarkInfo, Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = (imageWidth - watermarkInfo.getWatermarkWidth()) / 2;Integer y = imageHeight / 2 + (watermarkInfo.getWatermarkHeight() / 2);drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 左侧 配置** @param graphics* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void leftSideCompute(Graphics2D graphics, Integer imageHeight, WatermarkInfo watermarkInfo,Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = 0;Integer y = (imageHeight + watermarkInfo.getWatermarkHeight()) / 2;drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 右侧配置** @param graphics* @param imageWidth* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void rightSideCompute(Graphics2D graphics, Integer imageWidth, Integer imageHeight,WatermarkInfo watermarkInfo, Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = imageWidth - watermarkInfo.getWatermarkWidth();Integer y = (imageHeight + watermarkInfo.getWatermarkHeight()) / 2;drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 正上方配置** @param graphics* @param imageWidth* @param watermarkInfo* @param watermarkType* @param watermark*/public static void directlyAboveCompute(Graphics2D graphics, Integer imageWidth, WatermarkInfo watermarkInfo,Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = (imageWidth - watermarkInfo.getWatermarkWidth()) / 2;Integer y = watermarkInfo.getWatermarkHeight();drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 正下方** @param graphics* @param imageWidth* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void directlyBelowCompute(Graphics2D graphics, Integer imageWidth, Integer imageHeight,WatermarkInfo watermarkInfo, Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = (imageWidth - watermarkInfo.getWatermarkWidth()) / 2;Integer y = imageHeight;drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 左上角** @param graphics* @param watermarkInfo* @param watermarkType* @param watermark*/public static void upperLeftCompute(Graphics2D graphics, WatermarkInfo watermarkInfo, Integer watermarkType,String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = 0;Integer y = watermarkInfo.getWatermarkHeight();drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 左下角** @param graphics* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void lowerLeftCompute(Graphics2D graphics, Integer imageHeight, WatermarkInfo watermarkInfo,Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = 0;Integer y = imageHeight;drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 右上方** @param graphics* @param imageWidth* @param watermarkInfo* @param watermarkType* @param watermark*/public static void upperRightCompute(Graphics2D graphics, Integer imageWidth, WatermarkInfo watermarkInfo,Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = imageWidth - watermarkInfo.getWatermarkWidth();Integer y = watermarkInfo.getWatermarkHeight();drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 右下方** @param graphics* @param imageWidth* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void lowerRightCompute(Graphics2D graphics, Integer imageWidth, Integer imageHeight,WatermarkInfo watermarkInfo, Integer watermarkType, String watermark) {// 设置水印的坐标(为原图片中间位置)Integer x = imageWidth - watermarkInfo.getWatermarkWidth();Integer y = imageHeight;drawTestOrImage(graphics, x, y, watermarkType, watermark, watermarkInfo);}/*** 平铺** @param graphics* @param imageWidth* @param imageHeight* @param watermarkInfo* @param watermarkType* @param watermark*/public static void tileDrawCompute(Graphics2D graphics, Integer imageWidth, Integer imageHeight,WatermarkInfo watermarkInfo, Integer watermarkType, String watermark) {Integer watermarkHeight = watermarkInfo.getWatermarkHeight();Integer watermarkWidth = watermarkInfo.getWatermarkWidth();// 间隔Integer split = watermarkHeight * 2;// x,y可以绘制的数量,多加一个补充空白int xCanNum = imageWidth / watermarkWidth + 1;int yCanNum = imageHeight / watermarkHeight + 1;for (int i = 1; i <= yCanNum; i++) {int y = watermarkHeight * i + split * i;for (int j = 0; j < xCanNum; j++) {int x = watermarkWidth * j + split * j;drawTestOrImage(graphics, x, y - (watermarkHeight + split) * j, watermarkType, watermark,watermarkInfo);}}}/*** 画文字水印或图片水印** @param graphics* @param x* @param y* @param watermarkType* @param watermark* @param watermarkInfo*/public static void drawTestOrImage(Graphics2D graphics, int x, int y, Integer watermarkType, String watermark,WatermarkInfo watermarkInfo) {// 文字水印if (WatermarkTypeEnum.TEXT_WATERMARK.getCode().equals(watermarkType)) {graphics.drawString(watermark, x, y);} else {// 图片水印graphics.drawImage(watermarkInfo.getWatermarkBufferedImage(), x, y - watermarkInfo.getWatermarkHeight(), watermarkInfo.getWatermarkWidth(),watermarkInfo.getWatermarkHeight(), null);}}/*** 获取水印文字的长度** @param watermarkContent 文字水印内容* @param graphics 图像类* @return*/private static Integer getWatermarkLength(String watermarkContent, Graphics2D graphics) {return graphics.getFontMetrics(graphics.getFont()).charsWidth(watermarkContent.toCharArray(), 0,watermarkContent.length());}/*** 将图片写入到指定位置** @param bufImg* @param tarImgPath*/public static void writeImage(BufferedImage bufImg, String tarImgPath) {// 输出图片try {FileOutputStream outImgStream = new FileOutputStream(tarImgPath);ImageIO.write(bufImg, "png", outImgStream);outImgStream.flush();outImgStream.close();} catch (IOException e) {throw new RuntimeException(e);}}/*** 读取图片** @param path* @return*/public static BufferedImage readPicture(String path) {try {// 尝试获取本地return readLocalPicture(path);} catch (Exception e) {// 尝试获取网路return readNetworkPicture(path);}}/*** 读取本地图片** @param path* @return*/public static BufferedImage 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 BufferedImage 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 args*/public static void main(String[] args) {// 要处理的图片路径:String localPath = "/Users/wangjing/Desktop/watermark/image/test1.jpg";// 定义存储的地址String tarImgPath = "/Users/wangjing/Desktop/watermark/image/";// 文字水印内容String textWatermark = "刘亦菲";// 根据图片的背景设置水印颜色Color color = new Color(255, 255, 255, 128);// 设置字体 画笔字体样式为微软雅黑,加粗,文字大小为45ptFont font = new Font("微软雅黑", Font.BOLD, 45);for (int i = 1; i < 12; i++) {BufferedImage bufferedImage = readPicture(localPath);BufferedImage test = addWatermark(bufferedImage, font, color, WatermarkTypeEnum.TEXT_WATERMARK.getCode(),i, textWatermark);writeImage(test, tarImgPath + "watermark_text_" + i + ".jpg");}}/*** 图片水印测试** @param args*/
// public static void main(String[] args) {
//
// // 要处理的图片路径:
// String localPath = "https://vrar-obs-production.obs.cn-north-4.myhuaweicloud.com/survey/watermark/image.jpg";
//
// // 定义存储的地址
// String tarImgPath = "/Users/wangjing/Desktop/watermark/image/";
//
// // 图片水印内容
// String textWatermark = "https://vrar-obs-production.obs.cn-north-4.myhuaweicloud" +
// ".com/survey/watermark/watermark.png";
//
//
// for (int i = 1; i < 12; i++) {
// BufferedImage bufferedImage = readPicture(localPath);
// BufferedImage test = addWatermark(bufferedImage, null, null, WatermarkTypeEnum.IMAGE_WATERMARK.getCode(), i,
// textWatermark);
// writeImage(test, tarImgPath + "watermark_image_" + i + ".jpg");
// }
// }}
二、看效果
2.1,原图
2.2,文字水印生成效果
2.3,水印图片
2.4,图片水印生成效果
注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!