首页 > 编程语言 > 详细

javacv之于视频/GIF解帧及重新拼接生成GIF实现

时间:2019-05-09 12:14:38      阅读:163      评论:0      收藏:0      [点我收藏+]

  预备接手表情包处理业务,前期处理并不复杂,流程包括 : GIF动图与视频的解帧 , 逐帧处理, 组合各帧得到新的GIF. 经过调研, 整合了ffmpeg的Java CV 可完美处理解帧 , animated-gif-lib 组件包含gif生成的成熟方案 , 进而问题解决.

  animated-gif-lib + Java CV

  animated-gif-lib.jar是用来拆分和合成GIF的工具包,主要用到其中的GifDecoder/AnimatedGifEncoder.

  Java CV 常用于音频/图片等处理,其中整合了常用的c++类库,例如音频处理的ffmpeg,且可与Open CV配合使用.这里主要用到FFmpegFrameGrabber来取帧/Java2DFrameConverter来类型转换.

  其实,GifDecoder也可以完成解帧的过程,但实际使用中发现各帧颜色处理上有偏差,解帧问题较大.故而,采用Java CV来解帧,只使用其中合成GIF的操作.

  代码实现

  解帧,FFmpegFrameGrabber获取GIF总帧数时异常,故而采用GifDecoder获取

        String gifPath = "/home/lab/test/11.gif";
        String dirPath = "/home/lab/test/gif/";
        // 用以解帧
        FFmpegFrameGrabber grabberGif = new FFmpegFrameGrabber(gifPath);
        grabberGif.start();
        Frame frame ;
        // 用以获取GIF总帧数
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(gifPath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + gifPath + " error!");
        }
        // 类型转换,Frame -> BufferedImage
        Java2DFrameConverter converter = new Java2DFrameConverter();
        int frameCount = decoder.getFrameCount();
        for (int i = 0 ; i < frameCount ; i++) {
            String fileName = dirPath + "img_" + i + ".jpg";
            File outPut = new File(fileName);
            frame = grabberGif.grabImage();
            if (frame != null) {
                ImageIO.write(converter.getBufferedImage(frame),"jpg",outPut);
            }
        }
        grabberGif.stop();

  合成GIF

        int frameRate = 20;// 新GIF总帧数
        String resGif = "/home/lab/test/22.gif";
        FileOutputStream targetFile = new FileOutputStream(resGif); // 目标文件流
        int margin = 2; // 间隔帧数
        AnimatedGifEncoder en = new AnimatedGifEncoder();
        en.setFrameRate(frameRate);
        en.start(targetFile);
        for (int i = 0; i < frameRate; i++) {
            en.addFrame(converter.convert(grabberGif.grabImage()));
            grabberGif.setFrameNumber(grabberGif.getFrameNumber() + margin);
        }
        en.finish();
        grabberGif.stop();
        targetFile.close();

  原GIF倒序得到新GIF

        String gifPath = "/home/lab/test/11.gif";
        // 用以解帧
        FFmpegFrameGrabber grabberGif = new FFmpegFrameGrabber(gifPath);
        grabberGif.start();
        // 用以获取GIF总帧数
        GifDecoder decoder = new GifDecoder();
        int status = decoder.read(gifPath);
        if (status != GifDecoder.STATUS_OK) {
            throw new IOException("read image " + gifPath + " error!");
        }
        // 类型转换,Frame -> BufferedImage
        Java2DFrameConverter converter = new Java2DFrameConverter();
        int frameCount = decoder.getFrameCount();
        String resGif = "/home/lab/test/22.gif";
        FileOutputStream targetFile = new FileOutputStream(resGif); // 目标文件流
        AnimatedGifEncoder en = new AnimatedGifEncoder();
        en.setFrameRate(frameCount);
        en.start(targetFile);
        for (int i = frameCount - 1; i >= 0; i--) {
            grabberGif.setFrameNumber(i);
            en.addFrame(converter.convert(grabberGif.grabImage()));
        }
        en.finish();
        grabberGif.stop();
        targetFile.close();

   pom依赖

  因 javacv-platform依赖过重,实际引入的时候推荐指定系统版本的即可.开发机为64位Ubuntu,依赖如下

        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv</artifactId>
            <version>3.4.3-1.4.3</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.0.2-1.4.3</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacpp</artifactId>
            <version>1.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.0.2-1.4.3</version>
            <classifier>linux-x86_64</classifier>
        </dependency>
        <!-- gif -->
        <dependency>
            <groupId>com.madgag</groupId>
            <artifactId>animated-gif-lib</artifactId>
            <version>1.4</version>
        </dependency>

 

javacv之于视频/GIF解帧及重新拼接生成GIF实现

原文:https://www.cnblogs.com/nyatom/p/10837363.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!