【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. nyoj 169-素数 (打表)

    169-素数 内存限制:64MB 时间限制:3000ms 特判: No 通过数:42 提交数:84 难度:1 题目描述: 走进世博园某信息通信馆,参观者将获得前所未有的尖端互动体验,一场充满创想和喜悦 ...

  2. nyoj 277-车牌号 (map, pair, iterator)

    277-车牌号 内存限制:64MB 时间限制:3000ms 特判: No 通过数:9 提交数:13 难度:1 题目描述: 茵茵很喜欢研究车牌号码,从车牌号码上可以看出号码注册的早晚,据研究发现,车牌号 ...

  3. Vue项目使用CSS变量实现主题化

    主题化管理经常能在网站上看到,一般的思路都是将主题相关的CSS样式独立出来,在用户选择主题的时候加载相应的CSS样式文件.现在大部分浏览器都能很好的兼容CSS变量,主题化样式更容易管理了.最近,使用C ...

  4. Java-selenium

    public class chrometest { public static void main(String[] args) throws InterruptedException { Strin ...

  5. 使用 Rsync 从 Windows 同步数据到 Linux

    为什么要使用 rsync 从 Windows 到 linux 进行同步? 我们经常会面临这种的情况,项目使用 Windows 开发,最终部署在 Linux 上,但有时想要进行测试.维护.迭代版本时操作 ...

  6. 【故障公告】docker swarm 集群问题造成新版博客后台故障

    非常抱歉,今天下午 16:55~17:05 左右,由于 docker swarm 集群的突发不稳定问题造成新版博客后台(目前处于灰度发布阶段)无法正常使用,由此给您带来麻烦,请您谅解. 出故障期时,新 ...

  7. Alibaba Nacos 学习(一):Nacos介绍与安装

    Alibaba Nacos 学习(一):Nacos介绍与安装 Alibaba Nacos 学习(二):Spring Cloud Nacos Config Alibaba Nacos 学习(三):Spr ...

  8. 程序员常用6 个 Python 的日期时间库

    内建的 datetime 模块 在跳转到其他库之前,让我们回顾一下如何使用 datetime 模块将日期字符串转换为 Python datetime 对象. 假设我们从 API 接受到一个日期字符串, ...

  9. Spring与Redis整合(spring-data-redis)

    maven依赖 <properties> <!-- redis 版本 --> <redis.version>2.9.0</redis.version> ...

  10. html background-image 图片打开失败的原因

    写网页的时候遇到一个问题,在样式表里面引用background-image,没有出现效果.查了一下是提取图片的路径不对,记录下遇到问题以及解决方法. 1.系统自带url 引号问题 这个最坑,以为系统就 ...