• YUV转为RGB24(Java版本实现)


    YUV简介

    一般来说,直接采集到的视频数据是RGB24的格式,RGB24一帧的大小size=width×heigth×3 Byte,RGB32的size=width×heigth×4 Byte。如果是I420(即YUV标准格式4:2:0)的数据量是size=width×heigth×1.5 Byte。在采集到RGB24数据后,需要对这个格式的数据进行第一次压缩。即将图像的颜色空间由RGB24转化为IYUV。因为X264在进行编码的时候需要标准的YUV(4:2:0)。但是这里需要注意的是,虽然YV12也是(4:2:0),但是YV12和I420的却是不同的,在存储空间上面有些区别。区别如下:

    • YV12 : 亮度(行×列) + V(行×列/4) + U(行×列/4)
    • I420 : 亮度(行×列) + U(行×列/4) + V(行×列/4)

    可以看出,YV12和I420基本上是一样的,就是UV的顺序不同。

    YUV420p 和 YUV420的区别在于存储格式上有区别:

    • YUV420p:yyyyyyyy uuuu vvvvv
    • YUV420: yuv yuv yuv

    另外需要注意的是海康威视设备回调数据类型为YV12格式;而大华设备回调数据类型为YUV420格式。

    // YV12格式一个像素占1.5个字节
    private byte[] YV12_To_RGB24(byte[] yv12, int width, int height) {
    	if(yv12 == null) {
    		return null;
    	}
    	
    	int nYLen = (int)width * height;
    	int halfWidth = width >> 1;
    	
    	if(nYLen<1 || halfWidth<1) {
    		return null;
    	}
    	
    	// yv12's data structure  
    	// |WIDTH |  
    	// y......y--------  
    	// y......y   HEIGHT  
    	// y......y  
    	// y......y--------  
    	// v..v  
    	// v..v  
    	// u..u  
    	// u..u
    	
    	// Convert YV12 to RGB24
    	byte[] rgb24 = new byte[width * height * 3];
    	int[] rgb = new int[3];
    	int i, j, m, n, x, y;
    	m = -width;
    	n = -halfWidth;
    	for(y=0; y<height; y++) {
    		m += width;
    		if(y%2 != 0) {
    			n += halfWidth;
    		}
    		
    		for(x=0; x<width; x++) {
    			i = m+x;
    			j = n + (x>>1);
    			rgb[2] = (int)((int)(yv12[i]&0xFF) + 1.370705 * ((int)(yv12[nYLen+j]&0xFF) - 128)); // r  
    			rgb[1] = (int)((int)(yv12[i]&0xFF) - 0.698001 * ((int)(yv12[nYLen+(nYLen>>2)+j]&0xFF) - 128)  - 0.703125 * ((int)(yv12[nYLen+j]&0xFF) - 128));   // g  
    			rgb[0] = (int)((int)(yv12[i]&0xFF) + 1.732446 * ((int)(yv12[nYLen+(nYLen>>2)+j]&0xFF) - 128)); // b  
    			
    			//j = nYLen - iWidth - m + x;  
    			//i = (j<<1) + j;    //图像是上下颠倒的  
    			
    			j = m + x;
    			i = (j<<1) + j;
    				
    			for(j=0; j<3; j++) {
    				if(rgb[j]>=0 && rgb[j]<=255) {
    					rgb24[i+j] = (byte)rgb[j];
    				} else {
    					rgb24[i+j] = (byte) ((rgb[j] < 0)? 0 : 255);
    				}
    			}
    		}
    	}
    	
    	return rgb24;
    }
    

      

  • 相关阅读:
    java 的三种代理模式 (二)——子函数切面
    王者荣耀为什么不使用微服务架构,服务的极简主义,为什么交易网关使用redis做持久
    tcp_syncookies 半连接
    tcp_tw_recycle tcp_tw_reuse与timewait【yetdone】
    动态代理,没有被代理对象
    一次jstack解决update停顿
    动态代理反向
    注解的继承
    51单片机状态机键盘检测
    28335scififo中断接收与发送
  • 原文地址:https://www.cnblogs.com/xi-jie/p/14362177.html
Copyright © 2020-2023  润新知