maven引入坐标
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.4</version>
</dependency>
图片添加水印工具类
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
/**
* WaterMarkUtil
*
* @author Gavin
* @date 2024/5/9
*/
public class WaterMarkUtil {
// 水印透明度
private static final float alpha = 0.9f;
// 水印横向位置
private static int positionWidth = 100;
// 水印纵向位置
private static int positionHeight = 100;
// 水印文字字体
private static final Font font = new Font("宋体", Font.BOLD, 30);
// 水印文字颜色
private static final Color color = Color.white;
/**
* 给图片添加水印文字
*
* @param text 水印文字
* @param srcImgPath 源图片路径
* @param targetPath 目标图片路径
*/
public static void markImage(String text, String srcImgPath, String targetPath) {
markImage(text, srcImgPath, targetPath, null);
}
/**
* 给图片添加水印文字、可设置水印文字的旋转角度
*
* @param text
* @param srcImgPath
* @param targetPath
* @param degree
*/
public static void markImage(String text, String srcImgPath, String targetPath, Integer degree) {
OutputStream os = null;
try {
// 0、图片类型
String type = srcImgPath.substring(srcImgPath.indexOf(".") + 1, srcImgPath.length());
// 1、源图片
Image srcImg = ImageIO.read(new File(srcImgPath));
int imgWidth = srcImg.getWidth(null);
int imgHeight = srcImg.getHeight(null);
BufferedImage buffImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 2、得到画笔对象
Graphics2D g = buffImg.createGraphics();
// 3、设置对线段的锯齿状边缘处理
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(srcImg.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), 0, 0, null);
// 4、设置水印旋转
if (null != degree) {
g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
// 5、设置水印文字颜色
g.setColor(color);
// 6、设置水印文字Font
g.setFont(font);
// 7、设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
positionWidth = 50;
positionHeight = imgHeight-30;
g.drawString(text,positionWidth, positionHeight);
// 9、释放资源
g.dispose();
// 10、生成图片
os = new FileOutputStream(targetPath);
// ImageIO.write(buffImg, "JPG", os);
ImageIO.write(buffImg, type.toUpperCase(), os);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != os){
os.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 给图片添加水印文字、可设置水印文字的旋转角度
* @param text
* @param inputStream
* @param outputStream
* @param degree
* @param typeName
*/
public static void markImageByIO(String text, InputStream inputStream, OutputStream outputStream,
Integer degree, String typeName) {
try {
// 1、源图片
Image srcImg = ImageIO.read(inputStream);
int imgWidth = srcImg.getWidth(null);
int imgHeight = srcImg.getHeight(null);
BufferedImage buffImg = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
// 2、得到画笔对象
Graphics2D g = buffImg.createGraphics();
// 3、设置对线段的锯齿状边缘处理
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(srcImg.getScaledInstance(imgWidth, imgHeight, Image.SCALE_SMOOTH), 0, 0, null);
// 4、设置水印旋转
if (null != degree) {
g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2);
}
// 5、设置水印文字颜色
g.setColor(color);
// 6、设置水印文字Font
g.setFont(font);
// 7、设置水印文字透明度
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
// 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
g.drawString(text, positionWidth, positionHeight);
// 9、释放资源
g.dispose();
// 10、生成图片
ImageIO.write(buffImg, typeName.toUpperCase(), outputStream);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String srcImgPath = "C:\\Users\\admin\\Desktop\\测试图片\\1.png";
String text = "JCccc";
// 给图片添加水印文字
markImage(text, srcImgPath, "C:\\Users\\admin\\Desktop\\测试图片\\testSmileWithMark.jpg");
// 给图片添加水印文字,水印文字旋转-45
markImage(text, srcImgPath, "C:\\Users\\admin\\Desktop\\测试图片\\testSmileWithMarkRotate.jpg", -45);
System.out.println("给图片添加水印文字完毕");
}
视频添加水印工具类
import com.cgw.api.enumer.ApiStatus;
import com.cgw.common.core.exception.ParamException;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.bytedeco.opencv.opencv_core.IplImage;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
/**
* WaterMarkUtils
*
* @author Gavin
* @date 2024/5/9
*/
@Slf4j
public class WaterMarkUtils {
/**
* 水印字体
*/
private static Font FONT;
/**
* 透明度
*/
private static final AlphaComposite COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);
/**
* 水印之间的间隔
*/
private static final int X_MOVE = 50;
/**
* 水印之间的间隔
*/
private static final int Y_MOVE = 50;
/**
* 字体名称
*/
private static String font_Name = "宋体";
/**
* 图片上传加水印
* @param file
* @param waterMarkContent
* @return
*/
public static InputStream markWithContentByStream(MultipartFile file, String waterMarkContent){
try(
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
InputStream inputStream = file.getInputStream();
){
Color markContentColor = new Color(180,180,180);
// 读取原图片信息
BufferedImage srcImg = ImageIO.read(inputStream);
// 图片宽、高
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);
// 设置水印颜色
createText(markContentColor, waterMarkContent, bufImg, imgWidth, imgHeight, graphics);
ImageIO.write(bufImg, "jpg", outputStream);
return new ByteArrayInputStream(outputStream.toByteArray());
} catch (IOException e) {
e.printStackTrace();
log.error("图片加水印失败",e);
throw ParamException.le(ApiStatus.FILE_UPLOAD_FAIL);
}
}
/**
* 图片打水印(文字)
*
* @param srcImgPath 源文件地址
* @param waterMarkContent 水印内容
* @param outImgPath 输出文件的地址
*/
public static void markWithContentByImage(String srcImgPath,String waterMarkContent,String outImgPath) {
try {
Color markContentColor = new Color(180,180,180);
// 读取原图片信息
File srcFile = new File(srcImgPath);
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);
// 设置水印颜色
createText(markContentColor, waterMarkContent, bufImg, imgWidth, imgHeight, graphics);
// 输出图片
try (FileOutputStream fos = new FileOutputStream(outFile);){
ImageIO.write(bufImg, "jpg", fos);
}
} catch (Exception e) {
e.printStackTrace();
log.error("图片加水印失败",e);
throw ParamException.le(ApiStatus.FILE_UPLOAD_FAIL);
}
}
/**
* 视频打水印(文字)
*
* @param inputPath 源文件地址
* @param waterMarkContent 水印内容
* @param outputPath 输出文件的地址
*/
public static void markWithContentByVideo(String inputPath, String waterMarkContent, String outputPath) {
long l = System.currentTimeMillis();
File file = new File(inputPath);
// 抓取视频资源
Frame frame;
try(FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file)){
log.info("文件名-->>" + outputPath);
frameGrabber.start();
try (FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputPath, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels())){
recorder.setFormat("mp4");
recorder.setSampleRate(frameGrabber.getSampleRate());
recorder.setFrameRate(frameGrabber.getFrameRate());
recorder.setTimestamp(frameGrabber.getTimestamp());
recorder.setVideoBitrate(frameGrabber.getVideoBitrate());
recorder.setVideoCodec(frameGrabber.getVideoCodec());
recorder.start();
Color markContentColor = new Color(180,180,180);
while (true){
frame = frameGrabber.grabFrame();
if(frame == null){
log.info("视频处理完成");
break;
}
//判断图片帧
if(frame.image != null){
IplImage iplImage = Java2DFrameUtils.toIplImage(frame);
BufferedImage bufImg = Java2DFrameUtils.toBufferedImage(iplImage);
int imgWidth = iplImage.width();
int imgHeight = iplImage.height();
// 加水印
Graphics2D graphics = bufImg.createGraphics();
// 创建绘图工具
createText(markContentColor, waterMarkContent, bufImg, imgWidth, imgHeight, graphics);
Frame newFrame = Java2DFrameUtils.toFrame(bufImg);
recorder.record(newFrame);
}
//设置音频
if(frame.samples != null){
recorder.recordSamples(frame.sampleRate,frame.audioChannels,frame.samples);
}
}
recorder.stop();
recorder.release();
frameGrabber.stop();
}
}catch (Exception e){
e.printStackTrace();
log.error("视频加水印失败",e);
throw ParamException.le(ApiStatus.FILE_UPLOAD_FAIL);
}
}
private static void createText(Color markContentColor, String waterMarkContent, BufferedImage bufImg, int imgWidth, int imgHeight, Graphics2D graphics) {
// 设置水印颜色
graphics.setColor(markContentColor);
// 设置水印透明度
graphics.setComposite(COMPOSITE);
// 设置倾斜角度
/* graphics.rotate(Math.toRadians(-35), (double) bufImg.getWidth() / 2,
(double) bufImg.getHeight() / 2);*/
graphics.rotate(Math.toRadians(0), 100,
100);
// 设置水印字体
graphics.setFont(FONT);
// 消除java.awt.Font字体的锯齿
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int xCoordinate = -imgWidth / 2;
int yCoordinate;
// 字体长度
int markWidth = FONT.getSize() * getTextLength(waterMarkContent);
// 字体高度
int markHeight = FONT.getSize();
// 循环添加水印
double d = 1.5;
/* while (xCoordinate < imgWidth * d) {
//yCoordinate = -imgHeight / 2;
yCoordinate = -imgHeight;
while (yCoordinate < imgHeight * d) {
graphics.drawString(waterMarkContent, xCoordinate, yCoordinate);
yCoordinate += markHeight + Y_MOVE;
}
xCoordinate += markWidth + X_MOVE;
}*/
graphics.drawString(waterMarkContent, 100, 100);
// 释放画图工具
graphics.dispose();
}
/**
* 计算水印文本长度
* 1、中文长度即文本长度 2、英文长度为文本长度二分之一
* @param text 文字
* @return int
*/
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;
}
static {
try {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String[] fontNames = ge.getAvailableFontFamilyNames();
for (String fontName: fontNames){
if(fontName.equals(font_Name)){
FONT = new Font(font_Name, Font.BOLD, 40);
break;
}
}
if(FONT == null){
log.error("系统上未找到对应的字体加载本地字体!");
File dest = new File("/mnt/myStyle.ttf");
FONT = Font.createFont(Font.TRUETYPE_FONT, dest)
.deriveFont((float) 20);
}
} catch (FontFormatException | IOException e) {
log.error("水印字体加载失败!",e);
e.printStackTrace();
}
}
public static void main(String[] args) {
/* markWithContentByImage("C:\\Users\\admin\\Desktop\\测试图片\\1.png",
"测试水印","C:\\Users\\admin\\Desktop\\测试图片\\1111.png");*/
markWithContentByVideo("C:\\Users\\admin\\Desktop\\测试图片\\2.mp4",
"测试水印","C:\\Users\\admin\\Desktop\\测试图片\\55555.mp4");
}