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

【Java SE】使用Javacv截取视频图片的更多相关文章

  1. C#利用开源软件ffMpeg截取视频图片

    #region 从视频画面中截取一帧画面为图片 /// <summary> /// 从视频画面中截取一帧画面为图片 /// </summary> /// <param n ...

  2. 使用javacv 截取视频指定帧节

    个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...

  3. (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片

    你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...

  4. iOS截取视频缩略图的两种方法

    前言: 看完了使用MPMoviePlayerController播放在线视频,在实际应用中有时候须要获取视频的缩略图,我们来看看怎样截取指定时间内的视频缩略图. 一  使用MPMoviePlayerC ...

  5. FFmpeg-截取视频图片

    FFmpeg-截取视频图片 标签(空格分隔): linux 安装FFmpeg 官网:http://www.ffmpeg.org/ 这里主要是linux环境下的安装 1. wget http://ffm ...

  6. javacv——读取摄像头的图像、截取视频的画面

    javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能). 这些需要引入的包.音视频处理使用ff ...

  7. javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作

    欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) javaCV图像处理系列: javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体.位置. ...

  8. Java截取视频文件缩略图

    /** * 截取视频第0帧的图片 */public static void videoImage(String filePath, String fileName,int widthdist, int ...

  9. php ffmpeg截取视频第一帧保存为图片的方法

    php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...

随机推荐

  1. 100天搞定机器学习|Day56 随机森林工作原理及调参实战(信用卡欺诈预测)

    本文是对100天搞定机器学习|Day33-34 随机森林的补充 前文对随机森林的概念.工作原理.使用方法做了简单介绍,并提供了分类和回归的实例. 本期我们重点讲一下: 1.集成学习.Bagging和随 ...

  2. iOS核心动画高级技巧-1

    1. 图层树 图层的树状结构 巨妖有图层,洋葱也有图层,你有吗?我们都有图层 -- 史莱克 Core Animation其实是一个令人误解的命名.你可能认为它只是用来做动画的,但实际上它是从一个叫做L ...

  3. ES6 Map 原理

    ES6的Map的键可以是任意的数据结构,并且不重复. 那么map的底层原理是啥呢? Map利用链表,hash的思想来实现. 首先,Map可以实现删除,而且删除的数据可以是中间的值.而链表的优势就是在中 ...

  4. 使用Executor框架创建线程池

    Executor框架 Executor类:在java.util.concurrent类中,是JDK并发包的核心类. ThreadPoolExecutor: 线程池. Excutors: 线程池工厂,通 ...

  5. 用Swoole+React 实现的聊天室

    前后端分离的项目,使用 Swoole+React 实现的聊天室,整个项目的框架结构可以进行参考,前端 react+react-redux+react-router+react-ant 等等,后台使用 ...

  6. Java基础知识总结之垃圾回收机制

    垃圾回收机制 Java垃圾回收机制是Java语言的重要功能之一.当程序创建对象,数组等引用类型对象时,系统会自动在内存区为之分配一块内存,对象就保存在这块内存区内,当这块内存不再被任何变量引用时,这块 ...

  7. (四十二)golang--管道

    假设我们现在有这么一个需求: 计算1-200之间各个数的阶乘,并将每个结果保存在mao中,最终显示出来,要求使用goroutime. 分析: (1)使用goroutime完成,效率高,但是会出现并发/ ...

  8. 【NHOI2018】扫雷完成图

    [题目描述] 扫雷游戏完成后会显示一幅图,图中标示了每个格子的地雷情况.现在,一个 n * n 方阵中有 k 个地雷,请你输出它的扫雷完成图. [输入数据] 输入共 k+1 行: 第 1 行为 2 个 ...

  9. Linux的awk命令详解

    awkawk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,默认以空格为分隔符将每行切片,切开的部分再 ...

  10. 用Spring Security, JWT, Vue实现一个前后端分离无状态认证Demo

    简介 完整代码 https://github.com/PuZhiweizuishuai/SpringSecurity-JWT-Vue-Deom 运行展示 后端 主要展示 Spring Security ...