java從視訊中獲截幀生成靜態圖與GIF,圖片旋轉
阿新 • • 發佈:2018-12-10
pom:
<!-- 視訊截圖 --> <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4.2</version> </dependency> <!-- gif --> <dependency> <groupId>com.madgag</groupId> <artifactId>animated-gif-lib</artifactId> <version>1.4</version> </dependency>
import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.imageio.ImageIO; import org.bytedeco.javacv.FFmpegFrameGrabber; import org.bytedeco.javacv.Frame; import org.bytedeco.javacv.Java2DFrameConverter; import com.madgag.gif.fmsware.AnimatedGifEncoder; public class TestMain { /** * 擷取視訊指定幀生成gif * @param videofile 視訊檔案 * @param startFrame 開始幀 * @param frameCount 擷取幀數 * @param frameRate 幀頻率(預設:3) * @param margin 每擷取一次跳過多少幀(預設:3) * @throws IOException 擷取的長度超過視訊長度 */ public static void buildGif(String videofile,int startFrame,int frameCount,Integer frameRate,Integer margin) throws IOException { if(margin==null)margin=3; if(frameRate==null)frameRate=3; FileOutputStream targetFile = new FileOutputStream(videofile.substring(0,videofile.lastIndexOf("."))+".gif"); FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); Java2DFrameConverter converter = new Java2DFrameConverter(); ff.start(); try { if(startFrame>ff.getLengthInFrames() & (startFrame+frameCount)>ff.getLengthInFrames()) { throw new RuntimeException("視訊太短了"); } ff.setFrameNumber(startFrame); AnimatedGifEncoder en = new AnimatedGifEncoder(); en.setFrameRate(frameRate); en.start(targetFile); for(int i=0;i<frameCount;i++) { en.addFrame(converter.convert(ff.grab())); ff.setFrameNumber(ff.getFrameNumber()+margin); } en.finish(); }finally { ff.stop(); ff.close(); } } /** * 將圖片旋轉指定度 * @param bufferedimage 圖片 * @param degree 旋轉角度 * @return */ public static BufferedImage rotateImage(BufferedImage bufferedimage,int degree){ int w= bufferedimage.getWidth();// 得到圖片寬度。 int h= bufferedimage.getHeight();// 得到圖片高度。 int type= bufferedimage.getColorModel().getTransparency();// 得到圖片透明度。 BufferedImage img;// 空的圖片。 Graphics2D graphics2d;// 空的畫筆。 (graphics2d= (img= new BufferedImage(w, h, type)) .createGraphics()).setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);// 旋轉,degree是整型,度數,比如垂直90度。 graphics2d.drawImage(bufferedimage, 0, 0, null);// 從bufferedimagecopy圖片至img,0,0是img的座標。 graphics2d.dispose(); return img;// 返回複製好的圖片,原圖片依然沒有變,沒有旋轉,下次還可以使用。 } /** * 擷取視訊指定幀儲存為指定格式的圖片(圖片儲存在視訊同文件夾下) * @param videofile 視訊地址 * @param imgSuffix 圖片格式 * @param indexFrame 第幾幀(預設:5) * @throws Exception */ public static void fetchFrame(String videofile,String imgSuffix,Integer indexFrame)throws Exception { if(indexFrame==null)indexFrame=5; FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); ff.start(); try { int lenght = ff.getLengthInFrames(); int i = 0; Frame f = null; while (i < lenght) { f = ff.grabFrame(); if ((i > indexFrame) && (f.image != null)) { break; } i++; } int owidth = f.imageWidth ; int oheight = f.imageHeight ; int width = 800; int height = (int) (((double) width / owidth) * oheight); Java2DFrameConverter converter =new Java2DFrameConverter(); BufferedImage fecthedImage =converter.getBufferedImage(f); BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR); bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); bi=rotateImage(bi, 90); File targetFile = new File(videofile.substring(0,videofile.lastIndexOf("."))+imgSuffix); ImageIO.write(bi, "jpg", targetFile); }finally { ff.stop(); ff.close(); } } public static void main(String[] args) { try { //fetchFrame("D:\\test\\QQ.mp4",".jpg",10); buildGif("D:\\test\\QQ.mp4", 5, 20, 3,3); } catch (Exception e) { e.printStackTrace(); } } }