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