• javacpp-FFmpeg系列之3: 像素图像数据转换(BGR与BufferdImage互转,RGB与BufferdImage互转,BufferdImage转Base64编码)


    javacpp-ffmpeg系列:

    javacpp-FFmpeg系列之1:视频拉流解码成YUVJ420P,并保存为jpg图片

    javacpp-FFmpeg系列之2:通用拉流解码器,支持视频拉流解码并转换为YUV、BGR24或RGB24等图像像素数据

    javacpp-FFmpeg系列之3: 图像数据转换(BGR与BufferdImage互转,RGB与BufferdImage互转)

    补充:

    javacpp-FFmpeg系列补充:FFmpeg解决avformat_find_stream_info检索时间过长问题

    前言

    ffmpeg获取的数据一般为yuv,argb,rgb,bgr,abgr等图像像素数据,我们可能需要转换为java的图像,来方便我们显示他们,当然不需要转换也可以达到我们的目的。

    在线演示demo:https://blog.csdn.net/eguid_1/article/details/82842904

    项目维护地址:https://github.com/eguid/easyCV

    一、那么先来个RGB像素使用的小demo压压惊

    (密集恐惧症预警)

    通过这个RGB像素的小demo,更容易理解RGB像素格式

    public static int getRGB(int[] rgbarr) {//RGB24数组转整型RGB24
            int rgb = ((int) rgbarr[0]) & 0xff | (((int) rgbarr[1]) & 0xff) << 8 | (((int) rgbarr[2]) & 0xff) << 16
                    | 0xff000000;
            return rgb;
        }
        private static int createRandomRgb() {//随机生成RGB24
            int[] rgbarr = new int[3];
            rgbarr[0] = (int) (Math.random() * 255);
            rgbarr[1] = (int) (Math.random() * 255);
            rgbarr[2] = (int) (Math.random() * 255);
            return getRGB(rgbarr);
        }

    //eguid原创文章,转载请注明出处和作者名(blog.csdn.net/eguid_1)
       public static void main(String[] args){
            int width = 800, height = 600;

    //使用整型RGB24
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    int rgb = createRandomRgb();
                    image.setRGB(i, j, rgb);
                }
            }
            JLabel label = new JLabel();
            label.setSize(width, height);
            label.setIcon(new ImageIcon(image));

            JFrame frame = new JFrame();
            frame.setSize(width, height);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(label);
            frame.setVisible(true);
            Timer timer=new Timer("定时刷新", true);
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    for (int i = 0; i < width; i++) {
                        for (int j = 0; j < height; j++) {
                            int rgb =createRandomRgb();
                            image.setRGB(i, j, rgb);
                        }
                    }
                    label.repaint();
                }
            }, 100, 1000/25);
        }

    运行结果:

    RGB像素格式demo截图-eguid

    二、像素图像数据转换为java图像

    上一章我们已经通过ffmpeg获取到了AVFrame,要是能预览这帧视频图像那岂不是更好?

    要完成转换为java的图像数据这个转换我们分为两步转换流程。

    1、像素图像转换为ByteBuffer

    不管是yuv,还是rgb或是bgr,都可以使用该函数转换为ByteBuffer,不同的是ByteBuffer转换为BufferedImage的异同。

    //eguid原创文章,转载请注明出处和作者名(https://blog.csdn.net/eguid_1)

    public ByteBuffer saveFrame(AVFrame pFrame, int width, int height){
            BytePointer data = pFrame.data(0);
            int size = width * height * 3;
            ByteBuffer buf = data.position(0).limit(size).asBuffer();
            return buf;
        }

    2、ByteBuffer转换为BufferImage

    由于不同像素数据转换方法都不相同,以RGB和BGR为例:

    (1)BGR24转BufferedImage

    /**
         * 24位BGR转BufferedImage
         * @param src -源数据
         * @param width -宽度
         * @param height-高度
         * @return
         */
        public static BufferedImage BGR2BufferedImage(ByteBuffer src,int width,int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            Raster ra = image.getRaster();
            DataBuffer out = ra.getDataBuffer();
            DataBufferByte db=(DataBufferByte)out;
            ByteBuffer.wrap(db.getData()).put(src);
            return image;
        }

    /**
         * 24位整型BGR转BufferedImage
         * @param src -源数据
         * @param width -宽度
         * @param height-高度
         * @return
         */
        public static  BufferedImage BGR2BufferedImage(IntBuffer src,int width,int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
            Raster ra = image.getRaster();
            DataBuffer out = ra.getDataBuffer();
            DataBufferInt db=(DataBufferInt)out;
            IntBuffer.wrap(db.getData()).put(src);
            return image;
        }

    (2)RGB24转BufferedImage

    /**
         * 24位整型RGB转BufferedImage
         * @param src -源数据
         * @param width -宽度
         * @param height-高度
         * @return
         */
        public static  BufferedImage RGB2BufferedImage(IntBuffer src,int width,int height) {
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Raster ra = image.getRaster();
            DataBuffer out = ra.getDataBuffer();
            DataBufferInt db=(DataBufferInt)out;
            IntBuffer.wrap(db.getData()).put(src);
            return image;
        }

    三、一个方便预览BufferImage的小函数

    /**
         * 使用窗口显示BufferedImage图片
         * @param image -BufferedImage
         */
        public static void viewImage(BufferedImage image) {
            int width=image.getWidth(),height=image.getHeight();
            JLabel label = new JLabel();
            label.setSize(width, height);
            label.setIcon(new ImageIcon(image));

            JFrame frame = new JFrame();
            frame.setSize(width, height);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(label);
            frame.setVisible(true);
        }

    四、补充

    1、BufferImage转Base64编码,方便网页显示

    /**
         * bufferedImage转base64
         * @param format -格式(jpg,png,bmp,gif,jpeg等等)
         * @return
         * @throws IOException
         */
        public static String bufferedImage2Base64(BufferedImage image, String format) throws IOException {
            Encoder encoder = Base64.getEncoder();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();// 字节流
            ImageIO.write(image, format, baos);// 写出到字节流
            byte[] bytes=baos.toByteArray();
            // 编码成base64
            String jpg_base64 = encoder.encodeToString(bytes);
            return jpg_base64;
        }

    2、保存成图片文件

    //eguid原创文章,转载请注明出处和作者名(blog.csdn.net/eguid_1)

    public static void saveImage(BufferedImage image,String format,String file) throws IOException {
            ImageIO.write(image, format, new File(file));
        }

  • 相关阅读:
    [记读书笔]python3.5实现socket通讯(UDP)
    [安全学习环境]Win7 下DVWA安装指南
    [Android]Android SDk Manager中创建模拟器无法选择CPU问题解析
    [其他]Android SDK离线文件路径以及安装更新方法
    [APP]如果你想反编译
    [Jmeter]jmeter之参数化
    常用性能相关工具
    DebugDiag收集Dump的使用说明
    Live Writer安装报错的问题,OnCatalogResult:0x80190194
    IIS不定期Crash和Oracle“未处理的内部错误(-2)”的问题分析
  • 原文地址:https://www.cnblogs.com/eguid/p/10195561.html
Copyright © 2020-2023  润新知