YUV图像格式转换: YUYV 转 NV12

首先确认YUYV与NV12 的采样格式, YUYV 属于YUV4:2:2采样, 而NV12属于YUV4:2:0采样。 采样方式如下图所示:
  采样方式

实心圆表示Y分量, 空心圆表示一对U和V的分量。并且YUV图像中每一个Y分量,即表示一个像素点。
  可以很明显地看出YUV422采样中两个像素点共用一对U和V的分量, 而YUV420采样中四个像素点共用一对U和V 的分量。有了这个概念,接下来的理解将十分轻松。

两者在存储方式上的表现如下图所示:
  
  存储方式对比在这里插入图片描述

在文件大小上,

  YUYV: filesize = width * height + width * height / 2 + width * height / 2
  NV12 : filesize = width * height + width * height / 4 + width * height / 4

即同条件的 NV12 文件大小是 YUYV 的 3/4。

那么你或许会烦躁了,怎么还不讲转化啊。别急,转换原理就是一两句话的事,上述都是铺垫。
  转换原理: YUV4:2:2 —> YUV4:2:0 Y不变,将U和V信号值在行(垂直方向)在进行一次隔行抽样。具体到YUYV 和NV12 上,则是仅需要注意存储方式的差别。
uv 分量隔行抽样

废话不多说了,直接上代码,可以转换多帧YUV图像格式:

void yuyv_to_nv12(char * image_in, char* image_out, int width, int height, unsigned long int filesize)
  {
       /* 计算循环次数,YUYV 一个像素点占2个字节*/
	   int pixNUM = width * height;
	   unsigned int cycleNum = filesize /pixNUM/2;
	   printf("cycleNUM = %d\n",cycleNum);
	   
	  /*单帧图像中 NV12格式的输出图像 Y分量 和 UV 分量的起始地址,并初始化*/
	  char *y = image_out;
	  char *uv = image_out + pixNUM ;
	 
	  char *start = image_in;
          unsigned int i =0; 
	  int j =0,k =0;
	  
	  /*处理Y分量*/
	  for(i= 0; i<cycleNum ;i++)
	  {
		int index =0;
		for(j =0; j< pixNUM*2; j=j+2) //YUYV单行中每两个字节一个Y分量
		{
			*(y+index) = *(start + j);
			index ++;
		}
		start = image_in + pixNUM*2*i;
		y= y + pixNUM*3/2;
	  }
      
      /**处理UV分量**/
	  start = image_in;
	  for(i= 0; i<cycleNum ;i++)
	  {
	    int uv_index = 0;
		for(j=0; j< height; j =j+2)  // 隔行, 我选择保留偶数行
		{
			for(k = j*width*2+1; k< width*2*(j+1); k=k+4) //YUYV单行中每四个字节含有一对UV分量
			{
				*(uv+ uv_index) = *(start + k);
				*(uv +uv_index+1) = *(start +k +2);
				uv_index += 2;
			}
		}
	    start = image_in + pixNUM*2*i;
	    uv =uv + pixNUM*3/2;
	  }	
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值