javacpp-FFmpeg系列之3: 像素影像數據轉換

  • 2019 年 11 月 1 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/eguid_1/article/details/82767187

前言

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的異同。

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、保存成圖片文件

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