javacpp-FFmpeg系列之3: 像素圖像數據轉換(BGR與BufferdImage互轉,RGB與BufferdImage互轉,BufferdImage轉Base64編碼)

javacpp-ffmpeg系列:java

javacpp-FFmpeg系列之1:視頻拉流解碼成YUVJ420P,並保存爲jpg圖片git

javacpp-FFmpeg系列之2:通用拉流解碼器,支持視頻拉流解碼並轉換爲YUV、BGR24或RGB24等圖像像素數據github

javacpp-FFmpeg系列之3: 圖像數據轉換(BGR與BufferdImage互轉,RGB與BufferdImage互轉)數組

補充:dom

javacpp-FFmpeg系列補充:FFmpeg解決avformat_find_stream_info檢索時間過長問題ide

前言函數

ffmpeg獲取的數據通常爲yuv,argb,rgb,bgr,abgr等圖像像素數據,咱們可能須要轉換爲java的圖像,來方便咱們顯示他們,固然不須要轉換也能夠達到咱們的目的。ui

在線演示demo:https://blog.csdn.net/eguid_1/article/details/82842904編碼

項目維護地址:https://github.com/eguid/easyCV.net

1、那麼先來個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

2、像素圖像數據轉換爲java圖像

上一章咱們已經經過ffmpeg獲取到了AVFrame,要是能預覽這幀視頻圖像那豈不是更好?

要完成轉換爲java的圖像數據這個轉換咱們分爲兩步轉換流程。

一、像素圖像轉換爲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;
    }

二、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;
    }

3、一個方便預覽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);
    }

4、補充

一、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;
    }

二、保存成圖片文件

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

相關文章
相關標籤/搜索