NV12转YU12以及YU12转NV12

YU12格式也叫I420格式,是YUV420p其中的一种,NV12是YUV420sp的一种。YU12和NV21中YUV数据的排列方式为:
YU12:YYYYYYYY UU VV
NV12:YYYYYYYY UV UV
针对数据的排列结构,本文将NV12转为YU12以及YU12转NV12。

NV12转为YU12

NV12转为YU12转换接口实现为:

int NV12toYU12(char *data, char *out, int width, int height);

功能描述 : Nv12格式转YU12
输入参数 :
data : NV12图片数据指针
out :YU12图片地址
width: 图像宽度
height : 图像高度
输出参数 : out,YU12图片地址
返 回 值 : int类型

具体代码如下:

/*
***********************************************************************
* 文件名称:Nv12toYU12.c
* 文件描述:Nv12格式转YU12
* 作   者:Young Fan	
*日   期:2021-09-16
************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*****************************************************************************
 函 数 名:   NV12toYU12
 功能描述  : Nv12格式转YU12
 输入参数  : data      NV12图片数据指针
             out       输出的YU12图片地址
             width     图像宽度
             height    图像高度
 输出参数  : 光栅格式yuv数据
 返 回 值  : int
*****************************************************************************/
int NV12toYU12(char *data, char *out, int width, int height)
{
	if (data == NULL || out == NULL)
	{
		printf("error:empty pointer \n");
		return -1;
	}
	if (width <= 0 || height <= 0)
	{
		printf("error:width or height is not positive \n");
		return -1;
	}
	
	//分别获取NV12数据中的Y、U、V分量。NV12:YYYYYYYY UVUV =>  YU12: YYYYYYYY UU VV
	//Y
	memcpy(out, data, width * height);
	printf("Y分量转换完成!\n");
	//U
	char * ptr1 = out + width * height; //YU12中U的首地址
	char * ptr2 = data + width * height;
	int n = 0;
	while (n < width * height / 4)
	{
		//赋值
		*(ptr1) = *(ptr2);
		ptr1++;
		ptr2 = ptr2 + 2;
		n++;
	}
	printf("U分量转换完成!\n");
	//V
	ptr1 = out + width * height * 5 / 4; //YU12中V的首地址
	ptr2 = data + width * height + 1;  
	n = 0;
	while (n < width * height / 4)
	{
		//赋值
		*(ptr1) = *(ptr2);
		ptr1++;
		ptr2 = ptr2 + 2;
		n++;
	}
	printf("V分量转换完成!\n");

	return 0;
}

int main(void)
{	
	int width = 512;
	int height = 288;
	int size = width * height * 3 / 2; 
	
	char *data = (char *)malloc(size);
	char *out = (char *)malloc(size);
	memset(data, 0, size);
	memset(out, 0, size);
	
	FILE *fp = fopen("./pic/NV12.yuv","rb");
	fread(data, 1, size, fp);
	
	int ret = NV12toYU12(data, out, width, height);
	if (ret < 0)
	{
		printf("error: NV12toYU12 failed, ret %d\n", ret);
		return -1;
	}
	
	//保存已转换好的YU12数据到本地
	FILE *out_fp = fopen("./out_YU12.yuv", "wb");
	fwrite(out, 1, size, out_fp);
	printf("整体转换完成并将YU12图像保存在本地!\n");
	
	//释放资源
	fclose(fp);
	fclose(out_fp);
	if(data != NULL)
	{
		free(data);
		data = NULL;
	}
	if(out != NULL)
	{
		free(out);
		out = NULL;
	}
	
    return 0;
}

打印输出如下:
在这里插入图片描述
输出图片:
在这里插入图片描述
原图:
在这里插入图片描述

YU12转NV12

YU12转NV12转换接口实现为:

int YU12toNV12(unsigned char *src[3], unsigned char *dst, int width, int height);

功能描述 : YU12转NV12
输入参数 :
unsigned char *src[3] : YU12图片地址,这里使用的是Y、U、V三个分量地址独立分开的
unsigned char *dst :NV12图片地址
width: 图像宽度
height : 图像高度
输出参数 : dst,NV12图片地址
返 回 值 : int类型

代码如下:

static int YU12toNV12(unsigned char *src[3], unsigned char *dst, int width, int height)
{
    if (src == NULL || dst == NULL)
	{
		printf("error:empty pointer \n");
		return -1;
	}
	if (width <= 0 || height <= 0)
	{
		printf("error:width or height is not positive \n");
		return -1;
	}
	
	//分别获取YU12数据中的Y、U、V分量。YU12: YYYYYYYY UU VV => NV12:YYYYYYYY UVUV   
	//Y
	memcpy(dst, src[0], width * height);
	printf("Y分量转换完成!\n");
    
	//U
	unsigned char * ptr1 = dst + width * height; //NV12中UV的首地址
	unsigned char * ptr2 = src[1]; //YU12中U的首地址
	unsigned char * ptr3 = src[2]; //YU12中V的首地址
	int n = 0;
	while (n < width * height / 4)
	{
		//赋值
		*(ptr1) = *(ptr2);
		ptr1++;
        ptr2++;
        *(ptr1) = *(ptr3);
        ptr1++;
        ptr3++;
		n++;
	}
	printf("UV分量转换完成!\n");

	return 0;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值