【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));
}
}
【Java SE】使用Javacv截取视频图片的更多相关文章
- C#利用开源软件ffMpeg截取视频图片
#region 从视频画面中截取一帧画面为图片 /// <summary> /// 从视频画面中截取一帧画面为图片 /// </summary> /// <param n ...
- 使用javacv 截取视频指定帧节
个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...
- (转载)[FFmpeg]使用ffmpeg从各种视频文件中直接截取视频图片
你曾想过从一个视频文件中提取图片吗?在Linux下就可以,在这个教程中我将使用ffmpeg来从视频中获取图片. 什么是ffmpeg?What is ffmpeg? ffmpeg是一个非常有用的命令行程 ...
- iOS截取视频缩略图的两种方法
前言: 看完了使用MPMoviePlayerController播放在线视频,在实际应用中有时候须要获取视频的缩略图,我们来看看怎样截取指定时间内的视频缩略图. 一 使用MPMoviePlayerC ...
- FFmpeg-截取视频图片
FFmpeg-截取视频图片 标签(空格分隔): linux 安装FFmpeg 官网:http://www.ffmpeg.org/ 这里主要是linux环境下的安装 1. wget http://ffm ...
- javacv——读取摄像头的图像、截取视频的画面
javacv开发包是用于支持java多媒体开发的一套开发包,可以适用于本地多媒体(音视频)调用以及音视频,图片等文件后期操作(图片修改,音视频解码剪辑等等功能). 这些需要引入的包.音视频处理使用ff ...
- javacpp-opencv图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体、位置、大小、粗度、翻转、平滑等操作
欢迎大家积极开心的加入讨论群 群号:371249677 (点击这里进群) javaCV图像处理系列: javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体.位置. ...
- Java截取视频文件缩略图
/** * 截取视频第0帧的图片 */public static void videoImage(String filePath, String fileName,int widthdist, int ...
- php ffmpeg截取视频第一帧保存为图片的方法
php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...
随机推荐
- 使用iis反向代理.net core应用程序
.net core 其实是自宿主性质的web应用程序,而不再是web网站,所以.net core是可以直接单独作为系统服务部署.但是实际情况中,为了同个一个端口能支持多个web应用和统一管理,还是应该 ...
- python接口自动化--Excel
1.操作步骤: (1)安装python官方Excel库-->xlrd (2)获取Excel文件位置并读取 (3)读取sheet (4)读取指定rows和cols内容 2.示例代码 # -*- c ...
- 自制反汇编工具使用实例 其二(使用xmm寄存器初始化对象,以及空的成员函数指针)
在反汇编代码中,当看到xmm寄存器,第一反应是将要进行浮点操作或访问,但是更加多的情况是在使用xmm寄存器初始化局部对象. 下面是自制反汇编工具翻译出来的代码: // -[CALayer setAll ...
- Linux考题(一)
1.创建目录/data/oldboy,并且在该目录下创建oldboy.txt,然后在文件oldybos.txt里写入内容“inet addr:192.168.228.128 Bcast:192.16 ...
- 20191107-5 beta week 2/2 Scrum立会报告+燃尽图 04
此作业的要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9957 一.小组情况 队名:扛把子 组长:孙晓宇 组员:宋晓丽 梁梦瑶 韩 ...
- FastDFS搭建分布式文件系统
FastDFS搭建分布式文件系统 1. 什么是分布式文件系统 分布式文件系统(Distributed File System)是指文件系统管理的物理存储资源不一定直接连接在本地节点上,而是通过计算机网 ...
- spring奇怪异常记录(会逐渐记录)
1 严重: Context initialization failedorg.springframework.beans.factory.BeanCreationException: Error cr ...
- GO 单例模式
wiki百科: 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对象的类必须保证只有一个实例存在.许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为.比 ...
- PHP的常用字符串处理
一.拼接字符串 拼接字符串是最常用到的字符串操作之一,在PHP中支持三种方式对字符串进行拼接操作,分别是圆点.分隔符{}操作,还有圆点等号.=来进行操作,圆点等号可以把一个比较长的字符串分解为几行进行 ...
- C# Lazy Loading
前言 按需加载对象延迟加载实际是推迟进行创建对象,直到对其调用后才进行创建初始化,延迟(懒加载)的好处是提高系统性能,避免不必要的计算以及不必要的资源浪费. 常规有这些情况: 对象创建成本高且程序可能 ...