JAVA 图片视频增加水印

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");
    }

要在视频添加水印,可以使用JavaCV库中的FFmpegFrameRecorder和FFmpegFrameFilter类。以下是一个简单的Java代码示例: ```java import org.bytedeco.javacpp.Loader; import org.bytedeco.javacv.*; import java.awt.*; import java.io.File; import java.io.IOException; public class VideoWatermarkAdder { public static void main(String[] args) throws FrameGrabber.Exception, FrameFilter.Exception, FrameRecorder.Exception, IOException { // 加载JavaCV依赖库 Loader.load(org.bytedeco.ffmpeg.ffmpeg.class); // 输入视频文件路径 String inputFile = "input.mp4"; // 输出视频文件路径 String outputFile = "output.mp4"; // 水印图片路径 String watermarkFile = "watermark.png"; // 创建视频源 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); grabber.start(); // 创建视频目标 FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels()); recorder.setFrameRate(grabber.getFrameRate()); recorder.setVideoCodec(grabber.getVideoCodec()); recorder.setAudioCodec(grabber.getAudioCodec()); recorder.start(); // 创建水印过滤器 FFmpegFrameFilter filter = new FFmpegFrameFilter("movie=" + watermarkFile + ":overlay=10:10", grabber.getImageWidth(), grabber.getImageHeight()); filter.start(); // 逐帧读取视频添加水印后写入目标视频 Frame frame; while ((frame = grabber.grabFrame()) != null) { // 添加水印 filter.push(frame); Frame filteredFrame = filter.pull(); // 写入目标视频 recorder.record(filteredFrame); } // 关闭资源 filter.stop(); recorder.stop(); grabber.stop(); // 显示输出文件路径 System.out.println("Output file saved to: " + new File(outputFile).getAbsolutePath()); } } ``` 该代码将在视频的左上角添加一个水印,并将处理后的视频保存到指定的输出文件路径。你需要将输入视频路径、输出视频路径和水印图片路径替换为你自己的路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值