• 【Java SE】使用Javacv截取视频图片


    【Java Web开发学习】使用Javacv截取视频图片

    转载:https://www.cnblogs.com/yangchongxing/p/9482935.html

    github地址:https://github.com/bytedeco/javacv

    Java不擅长处理视频和图片。使用场景是上传上来的视屏需要一个封面,所以就用java实现了。

    javacv文档很少,参考网上的代码稍作修改而成,仅供参考,有好的方式欢迎留言。

    网上有好多没有解决截屏图片被旋转过的问题,使用String rotate = grabber.getVideoMetadata("rotate");获取视频有没有旋转,没有返回null,有返回度数,90,180,270等。把图片做对象旋转,图片就正了。

    示例代码:select截取第20帧的图片

    public static void main(String[] args) throws IOException {
        // 截第20帧
        int select = 20;
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("E:/wx/下.mp4");
        grabber.start();
        int length = grabber.getLengthInFrames();
        int index = 1;
        Frame frame = null;
        while (index <= length) {
            frame = grabber.grab();
            if (index >= select) {
                break;
            }
            index++;
        }
        String rotate = grabber.getVideoMetadata("rotate");
        Java2DFrameConverter converter = new Java2DFrameConverter();
        BufferedImage bi = converter.getBufferedImage(frame);
        if (rotate != null) {
            //旋转图片
            bi = rotate(bi, Integer.parseInt(rotate));
        }
        ImageIO.write(bi, "jpg", new File("E:/wx/" + System.currentTimeMillis() + ".jpg"));
        grabber.stop();
    }
    public static BufferedImage rotate(BufferedImage src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        int type = src.getColorModel().getTransparency();
        Rectangle rect_des = calcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel);
        BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type);
        Graphics2D g2 = bi.createGraphics();
        g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
        g2.drawImage(src, 0, 0, null);
        g2.dispose();
        return bi;
    }
    public static Rectangle calcRotatedSize(Rectangle src, int angel) {
        if (angel >= 90) {
            if(angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);
        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }

    下面是一个上传截取第一帧做图片

    import java.awt.Dimension;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.imageio.ImageIO;
    import javax.servlet.http.HttpServletRequest;
    
    import org.bytedeco.javacv.FFmpegFrameGrabber;
    import org.bytedeco.javacv.Java2DFrameConverter;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.multipart.commons.CommonsMultipartFile;
    import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;
    
    @RequestMapping("/upload")
    @Controller
    public class UploadController extends BaseController {
        // 图片上传
        @RequestMapping(value="/image", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
        @ResponseBody
        public String uploadImage(@RequestParam(value = "imageFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException {
            if (imageFile == null || imageFile.getSize() == 0) {
                DefaultMultipartHttpServletRequest multipartRequest = (DefaultMultipartHttpServletRequest)request;
                imageFile = (CommonsMultipartFile) multipartRequest.getFile("Filedata");
                if (imageFile == null || imageFile.getSize() == 0) {
                    Result result = new Result();
                    result.setStatus(Result.STATUS_FAILURE);
                    result.setMessage(Result.STATUS_FAILURE);
                    return result.toJson();
                }
            }
            //文件名
            String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename());
            //日期目录
            String path = "/uploads/images" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            //服务器图片文件存放目录
            String serverPath = request.getServletContext().getRealPath(path);
            
            File serverPathFile = new File(serverPath);
            //目录不存在则创建
            if (!serverPathFile.exists()) {
                serverPathFile.mkdirs();
            }
            String imageUrl = path + fileName;
            String serverFilePath = serverPath + fileName;
            //移动文件
            imageFile.transferTo(new File(serverFilePath));return imageUrl;
        }
        // 视频上传
        @SuppressWarnings("resource")
        @RequestMapping(value="/video", method=RequestMethod.POST, produces="application/json;charset=UTF-8")
        @ResponseBody
        public String uploadVideo(@RequestParam(value = "videoFile", required = false) CommonsMultipartFile imageFile, HttpServletRequest request) throws IOException {
            if (imageFile == null || imageFile.getSize() == 0) {
                Result result = new Result();
                result.setStatus(Result.STATUS_FAILURE);
                result.setMessage("文件不存在");
                return result.toJson();
            }
            //文件名
            String fileName = Utils.fileName() + Utils.suffix(imageFile.getOriginalFilename());
            //日期目录
            String path = "/uploads/videos" + new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            //服务器图片文件存放目录
            String serverPath = request.getServletContext().getRealPath(path);
            
            File serverPathFile = new File(serverPath);
            //目录不存在则创建
            if (!serverPathFile.exists()) {
                serverPathFile.mkdirs();
            }
            String serverFilePath = serverPath + fileName;
            //移动文件
            imageFile.transferTo(new File(serverFilePath));
            
            //视频截屏
            FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(serverFilePath);
            grabber.start();
            Java2DFrameConverter converter = new Java2DFrameConverter();
            BufferedImage bi = converter.convert(grabber.grab());
            String rotate = grabber.getVideoMetadata("rotate");
            if (rotate != null) {
                bi = rotate(bi, Integer.parseInt(rotate));
            }
            fileName += ".v.jpg";
            serverFilePath = serverPath + fileName;
            String imageUrl = path + fileName;
            ImageIO.write(bi, "jpg", new File(serverFilePath));
            grabber.stop();
            // 返回截取封面
    return imageUrl; } public static BufferedImage rotate(BufferedImage src, int angel) { int src_width = src.getWidth(null); int src_height = src.getHeight(null); int type = src.getColorModel().getTransparency(); Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), angel); BufferedImage bi = new BufferedImage(rect_des.width, rect_des.height, type); Graphics2D g2 = bi.createGraphics(); g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2); g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2); g2.drawImage(src, 0, 0, null); g2.dispose(); return bi; } public static Rectangle CalcRotatedSize(Rectangle src, int angel) { if (angel >= 90) { if(angel / 90 % 2 == 1) { int temp = src.height; src.height = src.width; src.width = temp; } angel = angel % 90; } double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2; double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r; double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2; double angel_dalta_width = Math.atan((double) src.height / src.width); double angel_dalta_height = Math.atan((double) src.width / src.height); int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width)); int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height)); int des_width = src.width + len_dalta_width * 2; int des_height = src.height + len_dalta_height * 2; return new java.awt.Rectangle(new Dimension(des_width, des_height)); } }
  • 相关阅读:
    [CLR via C#]5.2 引用类型和值类型
    Yii easyWechat 开发的时候报错:cURL error 60: SSL certificate problem: unable to get local issuer certificat
    前端浏览器自动刷新神器:Browsersync
    phpStudy 切换版本后没有权限的问题
    最全的CSS浏览器兼容问题
    (转)详解JS位置、宽高属性之一:offset系列
    js 跨域问题
    移动端IOS 固定下方的输入框,点击输入框位置会变的修复
    ie8网页时调用特定的css文件
    Bootstrap如何禁止响应式布局 不适配
  • 原文地址:https://www.cnblogs.com/yangchongxing/p/9482935.html
Copyright © 2020-2023  润新知