JavaCV实现视频抽帧 JFrame字符动画

本文实现对视频进行抽帧,将视频图片转换成字符图片,在使用JFrame实现图片的连续播放。

javaCV实现对视频进行抽帧

		
		<dependency>
            <groupId>org.bytedecogroupId>
            <artifactId>javacvartifactId>
            <version>1.5.6version>
        dependency>
        <dependency>
            <groupId>org.bytedecogroupId>
            <artifactId>javacv-platformartifactId>
            <version>1.5.6version>
        dependency>
		// 进行视频的图片提取
		// 需要处理的视频位置
        String videoPath = "C:\\tmp\\videoDemo\\video\\1.mp4";
        // 存放图片的位置
        String imagePath = "C:\\tmp\\videoDemo\\image\\";
        // javaCv提供的视频处理
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath);
        ff.start();
        // 获取视频帧的长度
        int ffLength = ff.getLengthInFrames();
        System.out.println("ffLength = " + ffLength);
        // 提取视频中图片帧的间隔
        int interval = 1;
        for (int i = 0; i < ffLength; i++) {
            // 获取视频帧
            Frame frame = ff.grab();
            // 帧的类型
            EnumSet<Frame.Type> types = frame.getTypes();
            // VIDEO类型代表是图片,提取出来转换成图片
            if (types.contains(Frame.Type.VIDEO) && i % interval == 0) {
                if (frame.image == null) {
                    continue;
                }
                // 使用Java2DFrameConverter将帧转换成图片
                Java2DFrameConverter converter = new Java2DFrameConverter();
                String imgSuffix = "png";
                // 对应的目录写入图片
                String fileName = imagePath + File.separator + i + "." + imgSuffix;
                BufferedImage bufferedImage = converter.getBufferedImage(frame);
                ImageIO.write(bufferedImage, imgSuffix, new File(fileName));
                System.out.printf("执行:%d/%d%n", i, ffLength);
            }
        }
        ff.stop();
    }

以下是对视频进行提取后的图片:
JavaCV实现视频抽帧 JFrame字符动画_第1张图片

图片转换

// 将提取出来的视频图片转换成字符图片
        String imageDir = "C:\\tmp\\videoDemo\\image";
        String targetDir = "C:\\tmp\\videoDemo\\charImage\\";
        File imageDirFile = new File(imageDir);
        File[] files = imageDirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
            File file = files[i];
            String absolutePath = file.getAbsolutePath();
            String fileName = file.getName();
            String targetFile = targetDir + fileName;
            // 转换成对应的视频图片,转换方法https://blog.csdn.net/weixin_45485300/article/details/121716788
            ImageOut.characterPainting("love", 0, absolutePath, targetFile, false);
            System.out.printf("%d/%d%n", i, files.length);
        }

转换后:
JavaCV实现视频抽帧 JFrame字符动画_第2张图片

JFrame实现图片播放

public static void main(String[] args) {
        // 使用JFrame实现图片的播放
        ImageJPanel imageJPanel = new ImageJPanel();
        Thread thread = new Thread(imageJPanel);
        JFrame jFrame = new JFrame();
        // 添加图片
        jFrame.add(imageJPanel);
        // 设置尺寸,保持或图片大小一致即可
        jFrame.setSize(1920, 1080);
        // 设置可见
        jFrame.setVisible(true);
        // 窗口居中
        jFrame.setLocationRelativeTo(null);
        // 设置窗口关闭
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        thread.start();
    }

    static class ImageJPanel extends JPanel implements Runnable {

        // 进行渲染的图片
        private BufferedImage bufferedImage;

        // 图片地址
        private String path = "C:\\tmp\\videoDemo\\charImage";

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            if (bufferedImage != null) {
                // 绘制图片 参数是图片 x坐标 y坐标 图片渲染的一些回调通知,可以不用
                g.drawImage(bufferedImage, 0, 0, null);
            }
        }

        @Override
        public void run() {
            try {
                // 使用线程来加载的图片
                File file = new File(path);
                File[] files = file.listFiles();
                // 对图片进行一个排序,因为图片是按数字来命名的,读取的时候是按字典顺序来读取的,会出现114.png排在90.png的前面
                Arrays.sort(files, (f1, f2) -> {
                    String name = f1.getName();
                    String[] f1Index = name.split("\\.");
                    String f2Name = f2.getName();
                    String[] f2Index = f2Name.split("\\.");
                    return Integer.valueOf(f1Index[0]) - Integer.valueOf(f2Index[0]);
                });
                for (File imgFile : files) {
                    // 读取图片
                    bufferedImage = ImageIO.read(imgFile);
                    // 控制图片渲染的速度
                    Thread.sleep(50);
                    // 重新绘制
                    repaint();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

效果:

你可能感兴趣的:(动画,音视频,java)