【音视频】实操YUV与RGB互转(planar模式 YUV420、YUV422、YUV444与RGB888)

前言

提示:书写目的是为对YUV与RGB存储格式的了解,该代码可以直接用,也存在待优化的地方,后续优化,还请大家多多指点

编译环境:

LINUX下编译的,有gcc编译工具即可

看图工具:

	后续附上

文件列表

  • app_main.c 主函数
  • rgbtoyuv.c 处理文件
  • rgbtoyuv.h 头文件
  • Makefile 编译规则

1、主函数app_main.c

#include <stdio.h>
#include <stdlib.h>

#include "rgbtoyuv.h"
int main()
{
	//make_rgb24_colorbar();  
	char *RGBfilename = "rgb888.rgb";
	char *DstRGBfilename_1 = "dst_rgb888_1.rgb";
	char *DstRGBfilename_2 = "dst_rgb888_2.rgb";
	char *DstRGBfilename_3 = "dst_rgb888_3.rgb";
	char *DstRGBfilename_4 = "dst_rgb888_4.rgb";
	char *DstRGBfilename_5 = "dst_rgb888_5.rgb";
	char *DstRGBfilename_6 = "dst_rgb888_6.rgb";
	
	
	char *YUV420p_I420_filename = "yuv420p_I420.yuv";
	char *YUV420p_YV12_filename = "yuv420p_YV12.yuv";

	char *YUV422p_YU16_filename = "yuv422p_YU16.yuv";
	char *YUV422p_YV16_filename = "yuv422p_YV16.yuv";

	char *YUV444p_I444_filename = "yuv444p_I444.yuv";
	char *YUV444p_YV24_filename = "yuv444p_YV24.yuv";

	int iRgbSize = 0;
	int iRet = 0, i = 0;
	unsigned char c;

	
	FILE *fp_rgb 		= fopen(RGBfilename, "wb+");
	FILE *fp_rgb_dst_1 	= fopen(DstRGBfilename_1, "wb+");
	FILE *fp_rgb_dst_2 	= fopen(DstRGBfilename_2, "wb+");
	FILE *fp_rgb_dst_3 	= fopen(DstRGBfilename_3, "wb+");
	FILE *fp_rgb_dst_4 	= fopen(DstRGBfilename_4, "wb+");
	FILE *fp_rgb_dst_5 	= fopen(DstRGBfilename_5, "wb+");
	FILE *fp_rgb_dst_6 	= fopen(DstRGBfilename_6, "wb+");
	
	
	FILE *fp_YUV420p_I420 = fopen(YUV420p_I420_filename, "wb+");
	FILE *fp_yuv420p_YV12 = fopen(YUV420p_YV12_filename, "wb+");

	FILE *fp_yuv422p_YU16 = fopen(YUV422p_YU16_filename, "wb+");
	FILE *fp_yuv422p_YV16 = fopen(YUV422p_YV16_filename, "wb+");

	FILE *fp_yuv444p_I444 = fopen(YUV444p_I444_filename, "wb+");
	FILE *fp_yuv444p_YV24 = fopen(YUV444p_YV24_filename, "wb+");


	//-----------------------1、生成 RGB888 图像 -----------------------------
	iRgbSize = iamge_creat_rgb24(fp_rgb, IMAGE_W, IMAGE_H);

	if (iRgbSize == ERROR)
	{
		printf(" iamge_creat_rgb24 error \n");
		return 0;
	}
	fflush(fp_rgb);
	
	//---打印RGB实际数据
	/*
	fseek(fp_rgb, 0, SEEK_SET);
	for (i = 0; i < IMAGE_W*IMAGE_H * 3; i++)
	{
		if (i % (IMAGE_W * 3) == 0)
			printf("\n");
		fread(&c, 1, 1, fp_rgb);
		printf("%3d ",c);
	}
	*/
	

	printf("-----------write file %s totle  is %d bit \n", RGBfilename, iRgbSize);

	
	//-------------------------------- 2、图像转换  RGB_TO_YUV  -----------------------------

	//---YUV420p
	iRet = image_rgb888_to_yuv420p(fp_rgb, fp_YUV420p_I420, IMAGE_W, IMAGE_H, YUV420P_I420);
	if(iRet == ERROR)
	{
		printf(" image_rgb88_to_yuv420p error \n");
		goto RELASE;
	}
	fflush(fp_YUV420p_I420);
	printf("  [%d] image_rgb888_to_yuv420p  finish !!!!! \n",__LINE__);
	
	iRet = image_rgb888_to_yuv420p(fp_rgb, fp_yuv420p_YV12, IMAGE_W, IMAGE_H, YUV420P_YV12);
	if (iRet == ERROR)
	{
		printf(" image_rgb88_to_yuv420p error \n");
		goto RELASE;
	}
	fflush(fp_yuv420p_YV12);
	printf("  [%d] image_rgb888_to_yuv420p  finish !!!!! \n",__LINE__);




	//---YUV422p
	iRet = image_rgb888_to_yuv422p(fp_rgb, fp_yuv422p_YU16, IMAGE_W, IMAGE_H, YUV422P_YU16);
	if (iRet == ERROR)
	{
		printf(" image_rgb88_to_yuv420p error \n");
		goto RELASE;
	}
	fflush(fp_yuv422p_YU16);
	printf("  [%d] image_rgb888_to_yuv422p  finish !!!!! \n",__LINE__);

	iRet = image_rgb888_to_yuv422p(fp_rgb, fp_yuv422p_YV16, IMAGE_W, IMAGE_H, YUV422P_YV16);
	if (iRet == ERROR)
	{
		printf(" image_rgb888_to_yuv422p error \n");
		goto RELASE;
	}
	fflush(fp_yuv422p_YV16);
	printf("  [%d] image_rgb888_to_yuv422p  finish !!!!! \n",__LINE__);




	iRet = image_rgb888_to_yuv444p(fp_rgb, fp_yuv444p_I444, IMAGE_W, IMAGE_H, YUV444P_I444);
	if (iRet == ERROR)
	{
		printf(" image_rgb888_to_yuv444p error \n");
		goto RELASE;
	}
	fflush(fp_yuv444p_I444);

	iRet = image_rgb888_to_yuv444p(fp_rgb, fp_yuv444p_YV24, IMAGE_W, IMAGE_H, YUV444P_YV24);
	if (iRet == ERROR)
	{
		printf(" image_rgb888_to_yuv444p error \n");
		goto RELASE;
	}
	fflush(fp_yuv444p_YV24);

	//--------------------------------------------------------------------------------------------
	//-------------------------------------- YUV to RGB------------------------------------------------
	

	iRet = image_yuv444p_to_rgb888(fp_yuv444p_YV24, fp_rgb_dst_1, IMAGE_W, IMAGE_H, YUV444P_YV24);
	if (iRet == ERROR)
	{
		printf(" image_yuv444p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_1);

	iRet = image_yuv444p_to_rgb888(fp_yuv444p_I444, fp_rgb_dst_2, IMAGE_W, IMAGE_H, YUV444P_I444);
	if (iRet == ERROR)
	{
		printf(" image_yuv444p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_2);


	iRet = image_yuv420p_to_rgb888(fp_yuv420p_YV12, fp_rgb_dst_3, IMAGE_W, IMAGE_H, YUV420P_YV12);
	if (iRet == ERROR)
	{
		printf(" image_yuv420p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_3);



	iRet = image_yuv420p_to_rgb888(fp_YUV420p_I420, fp_rgb_dst_4, IMAGE_W, IMAGE_H, YUV420P_I420);
	if (iRet == ERROR)
	{
		printf(" image_yuv420p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_4);


	
	iRet = image_yuv422p_to_rgb888(fp_yuv422p_YV16, fp_rgb_dst_5, IMAGE_W, IMAGE_H, YUV422P_YV16);
	if (iRet == ERROR)
	{
		printf(" image_yuv422p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_5);

	iRet = image_yuv422p_to_rgb888(fp_yuv422p_YU16, fp_rgb_dst_6, IMAGE_W, IMAGE_H, YUV422P_YU16);
	if (iRet == ERROR)
	{
		printf(" image_yuv422p_to_rgb888 error \n");
		goto RELASE;
	}
	fflush(fp_rgb_dst_6);
	


 	printf("---------------------image change OK \n");

	fclose(fp_rgb);
	
	fclose(fp_YUV420p_I420);
	fclose(fp_yuv420p_YV12);
	
	fclose(fp_yuv422p_YU16);
	fclose(fp_yuv422p_YV16);
	
	fclose(fp_yuv444p_I444);
	fclose(fp_yuv444p_YV24);

	fclose(fp_rgb_dst_1);
	fclose(fp_rgb_dst_2);
	
	fclose(fp_rgb_dst_3);
	fclose(fp_rgb_dst_4);
	
	fclose(fp_rgb_dst_5);
	fclose(fp_rgb_dst_6);

	return OK;

	//----------------------------- 3、关闭句柄 -------------------------------------
RELASE:
	fclose(fp_rgb);
	
	fclose(fp_YUV420p_I420);
	fclose(fp_yuv420p_YV12);
	
	fclose(fp_yuv422p_YU16);
	fclose(fp_yuv422p_YV16);
	
	fclose(fp_yuv444p_I444);
	fclose(fp_yuv444p_YV24);

	fclose(fp_rgb_dst_1);
	fclose(fp_rgb_dst_2);
	
	fclose(fp_rgb_dst_3);
	fclose(fp_rgb_dst_4);
	
	fclose(fp_rgb_dst_5);
	fclose(fp_rgb_dst_6);

	return 0;
}

2、处理文件rgbtoyuv.c

/******************************************************************
 *
 *	待优化:
 *		1、转换函数中的写操作fread操作的参数
 *		2、malloc改为申请大空间 ,让程序不需要自己计算不同YUV格式需要的空间大小
 *
 *
 *
 *
 *
 *
 *
*************************************************************/

#include "rgbtoyuv.h"

#define IMAGE_PTR_CHEAK(p) \
		{\
			if(p == NULL)\
			{	\
				printf(" p == NULL !!!!!!");\
				return ERROR; \
			}	\
		}


#define IMAGE_ERROR(str) \
		{\
			printf("[%s] [%d] : IMAGE_ERROR : %s \n", __FUNCTION__, __LINE__, str);\
		}

#define IMAGE_YUV420_SIZE(w, h) ((w) * (h) * 3 / 2)	/**<---根据数据格式来判断大小 YUV420 按照 w * h * 3 * (3/6)*/

#define IMAGE_YUV422_SIZE(w, h)	((w) * (h) * 2)		/**<---根据数据格式来判断大小 YUV422 按照 w * h * 3 * (4/6)*/

#define IMAGE_YUV444_SIZE(w, h) ((w) * (h) * 3)		/**<---根据数据格式来判断大小 YUV444 按照 w * h * 3 * (3/3)*/

/**
* @brief   限幅像素的取值范围(内部函数)
* @param   [in] val 被限幅的像素值
* @param   [in] min_val 限幅最低值,建议最低为0
* @param   [in] max_val 限幅最高值,建议最高为255 
* @return  返回限幅后的像素值
*/
static inline unsigned char image_clip_value(unsigned char val, unsigned char min_val, unsigned char max_val)
{
	/*
	if (val > max_val) 
	{
		return max_val;
	}
	else if (val < min_val) 
	{
		return min_val;
	}
	else 
	{
		return val;
	}
	*/
	return val > max_val ? max_val : (val < min_val ? min_val : val);
}

/**
* @brief   将RGB24 图像转换 YUV420p  YUV数据(内部函数)
* @param   [out] pYUVBuf	输出的YUV420p图像数据
* @param   [in] YUVsize		输出的YUV420p图像数据
* @param   [in] RGBBuf		输入的RGB图像数据
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV420P_MODE_E 枚举变量	
* @return  OK / ERROR 成功/失败    
*/
static int rgb_to_yuv420p(unsigned char *pYUVBuf, unsigned int  YUVsize, unsigned char *RGBBuf, int w, int h, YUV420P_MODE_E mode)
{
	int i = 0, j = 0;
	unsigned char y, u, v, r, g, b;
	unsigned char *ptrY, *ptrU, *ptrV, *ptrRGB;

	IMAGE_PTR_CHEAK(pYUVBuf);
	IMAGE_PTR_CHEAK(RGBBuf);

	if (YUVsize < (unsigned int)IMAGE_YUV420_SIZE(w, h))
	{
		printf("YUVsize too small ,YUVsize = [%d], need size > [%d]\n", YUVsize, (unsigned int)IMAGE_YUV420_SIZE(w, h));
		return ERROR;
	}

	//---YUV420p存储V、U的两种方式区分:(每4个Y,公用一个U和V分量)
	ptrY = pYUVBuf;
	if (mode == YUV420P_I420)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h * 1 / 4);
	}
	else if(mode == YUV420P_YV12)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h * 1 / 4);
	}
	else
	{
		IMAGE_ERROR(" ------YUV420p mode dismatch !!!!!! ");
		return ERROR;
	}

	//---数据转换
	for (j = 0; j < h; j++)
	{
		ptrRGB = RGBBuf + w*j*3;
		for (i = 0; i < w; i++)
		{
			r = *(ptrRGB++);
			g = *(ptrRGB++);
			b = *(ptrRGB++);
			y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
			u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
			v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;

			*(ptrY) = image_clip_value(y, 0, 255);
			printf("Y");
			ptrY++;

			//---根据数据格式给每个像素上填充对应的Y、U、V分量
			if (j % 2 == 0 && i % 2 == 0)
			{
				*(ptrU) = image_clip_value(u, 0, 255);
				printf("U");
				ptrU++;
			}
			else
			{
				if (i % 2 == 0)
				{
					*(ptrV) = image_clip_value(v, 0, 255);
					printf("V");
					ptrV++;
				}
			}
		}
		printf("   [j = %d] \n", j);
	}
	return OK;
}


/**
* @brief   将RGB24 图像转换 YUV422p  YUV数据(内部函数)
* @param   [out] pYUVBuf	输出的YUV420p图像数据
* @param   [in] YUVsize		输出的YUV420p图像数据
* @param   [in] RGBBuf		输入的RGB图像数据
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV422P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
static int rgb_to_yuv422p(unsigned char *pYUVBuf, unsigned int  YUVsize, unsigned char *RGBBuf, int w, int h, YUV422P_MODE_E mode)
{
	int i = 0, j = 0;
	unsigned char y, u, v, r, g, b;
	unsigned char *ptrY, *ptrU, *ptrV, *ptrRGB;

	IMAGE_PTR_CHEAK(pYUVBuf);
	IMAGE_PTR_CHEAK(RGBBuf);

	if (YUVsize < (unsigned int)IMAGE_YUV422_SIZE(w, h))
	{
		printf("YUVsize too small ,YUVsize = [%d], need size > [%d]\n", YUVsize, (unsigned int)IMAGE_YUV422_SIZE(w, h));
		return ERROR;
	}

	//---YUV422p存储V、U的两种方式区分:(每2个Y,公用一个U和V分量)
	ptrY = pYUVBuf;
	if (mode == YUV422P_YU16)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h / 2);
	}
	else if (mode == YUV422P_YV16)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h / 2);
	}
	else
	{
		IMAGE_ERROR(" ------YUV422p mode dismatch !!!!!! ");
		return ERROR;
	}

	//---数据转换
	for (j = 0; j < h; j++)
	{
		ptrRGB = RGBBuf + w*j * 3;
		for (i = 0; i < w; i++)
		{
			r = *(ptrRGB++);
			g = *(ptrRGB++);
			b = *(ptrRGB++);
			y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;		//---根据公式得到,公式中的是小数,但是计算机中运算浮点型效率没有整形的高,所以做个转换
			u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
			v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;

			*(ptrY) = image_clip_value(y, 0, 255);
			printf("Y");
			ptrY++;

			//---根据数据格式给每个像素上填充对应的Y、U、V分量
			if (i % 2 == 0)
			{
				*(ptrV) = image_clip_value(v, 0, 255);
				printf("V");
				ptrV++;

				*(ptrU) = image_clip_value(u, 0, 255);
				printf("U");
				ptrU++;
			}
			
		}
		printf("   [j = %d] \n", j);
	}
	return OK;
}

/**
* @brief   将RGB24 图像转换 YUV444p  YUV数据(内部函数)
* @param   [out] pYUVBuf	输出的YUV420p图像数据
* @param   [in] YUVsize		输出的YUV420p图像数据
* @param   [in] RGBBuf		输入的RGB图像数据
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV444P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
static int rgb_to_yuv444p(unsigned char *pYUVBuf, unsigned int  YUVsize, unsigned char *RGBBuf, int w, int h, YUV444P_MODE_E mode)
{
	int i = 0, j = 0;
	unsigned char y, u, v, r, g, b;
	unsigned char *ptrY, *ptrU, *ptrV, *ptrRGB;

	IMAGE_PTR_CHEAK(pYUVBuf);
	IMAGE_PTR_CHEAK(RGBBuf);

	if (YUVsize < (unsigned int)IMAGE_YUV444_SIZE(w, h))	
	{
		printf("YUVsize too small ,YUVsize = [%d], need size > [%d]\n", YUVsize, (unsigned int)IMAGE_YUV444_SIZE(w, h));
		return ERROR;
	}

	//---YUV444p存储V、U的两种方式区分:(不丢失信息,无损)
	ptrY = pYUVBuf;
	if (mode == YUV444P_I444)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h);
	}
	else if (mode == YUV444P_YV24)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h);
	}
	else
	{
		IMAGE_ERROR(" ------YUV444p mode dismatch !!!!!! ");
		return ERROR;
	}

	//---数据转换
	for (j = 0; j < h; j++)
	{
		ptrRGB = RGBBuf + w*j * 3;
		for (i = 0; i < w; i++)
		{
			r = *(ptrRGB++);
			g = *(ptrRGB++);
			b = *(ptrRGB++);
			y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;		//---根据公式得到,公式中的是小数,但是计算机中运算浮点型效率没有整形的高,所以做个转换
			u = (unsigned char)((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
			v = (unsigned char)((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;

			*(ptrY) = image_clip_value(y, 0, 255);
			printf("Y");
			ptrY++;

			//---根据数据格式给每个像素上填充对应的Y、U、V分量

			*(ptrV) = image_clip_value(v, 0, 255);
			printf("V");
			ptrV++;

			*(ptrU) = image_clip_value(u, 0, 255);
			printf("U");
			ptrU++;


		}
		printf("   [j = %d] \n", j);
	}
	return OK;
}

/**
* @brief   将YUV422p 图像转换 RGB888(内部函数)
* @param   [out] RGBBuf		输出的RGB图像数据
* @param   [in] pYUVBuf		输入的YUV422p图像数据BUFF
* @param   [in] YUVsize		输入的YUV422p图像数据BUFF大小
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV420P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
static int yuv420p_to_rgb888(unsigned char *RGBBuf, unsigned char  *pYUVBuf, unsigned int YUVsize, int w, int h, YUV420P_MODE_E mode)
{
	int  i = 0, j = 0;
	unsigned char *ptrY, *ptrU, *ptrV;
	unsigned char y, u, v;
	unsigned char r, g, b;
	unsigned int  nv_index = 0, rgb_index = 0;

	IMAGE_PTR_CHEAK(pYUVBuf);
	IMAGE_PTR_CHEAK(RGBBuf);

	if (YUVsize < (unsigned int)IMAGE_YUV420_SIZE(w, h))
	{
		printf("YUVsize too small ,YUVsize = [%d], need size > [%d]\n", YUVsize, (unsigned int)IMAGE_YUV420_SIZE(w, h));
		return ERROR;
	}


	//---YUV420p存储V、U的两种方式区分:(每4个Y,公用一个U和V分量)
	ptrY = pYUVBuf;
	if (mode == YUV420P_I420)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h * 1 / 4);
	}
	else if(mode == YUV420P_YV12)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h * 1 / 4);
	}
	else
	{
		IMAGE_ERROR(" ------YUV420p mode dismatch !!!!!! ");
		return ERROR;
	}

	
	//---行扫描的方式
	for (i = 0; i < h; i++)
	{
		for (j = 0; j < w ; j++, rgb_index++ ) 
		{
			nv_index = (i / 2) * (w / 2) + (j / 2);

			y = *(ptrY++);
			u = *(ptrU + nv_index);
			v = *(ptrV + nv_index);

			r = y + ((351 * (v - 128)) >> 8);  //r
			g = y - ((179 * (v - 128) + 86 * (u - 128)) >> 8); //g
			b = y + ((443 * (u - 128)) >> 8); //b

			r = image_clip_value(r, 0, 255);
			g = image_clip_value(g, 0, 255);
			b = image_clip_value(b, 0, 255);
			

			RGBBuf[rgb_index * 3 + 0] = b;
			RGBBuf[rgb_index * 3 + 1] = g;
			RGBBuf[rgb_index * 3 + 2] = r;

		}

	}

}

/**
* @brief   将YUV422p 图像转换 RGB888(内部函数)
* @param   [out] RGBBuf		输出的RGB图像数据
* @param   [in] pYUVBuf		输入的YUV422p图像数据BUFF
* @param   [in] YUVsize		输入的YUV422p图像数据BUFF大小
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV422P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
static int yuv422p_to_rgb888(unsigned char *RGBBuf, unsigned char  *pYUVBuf, unsigned int YUVsize, int w, int h, YUV422P_MODE_E mode)
{
	int  i = 0, j = 0;
	unsigned char *ptrY, *ptrU, *ptrV;
	unsigned char y, u, v;
	unsigned char r, g, b;
	unsigned int  nv_index = 0, rgb_index = 0;

	//---YUV422p存储V、U的两种方式区分:(每4个Y,公用一个U和V分量)
	ptrY = pYUVBuf;
	if (mode == YUV422P_YU16)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h * 1 / 2);
	}
	else if(mode == YUV422P_YV16)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h * 1 / 2);
	}
	else
	{
		IMAGE_ERROR(" ------YUV422p mode dismatch !!!!!! ");
		return ERROR;
	}

	
	//---行扫描的方式
	for (i = 0; i < h; i++)
	{
		for (j = 0; j < w ; j++, rgb_index++ ) 
		{
			nv_index = (i) * (w / 2) + (j / 2);

			y = *(ptrY++);
			u = *(ptrU + nv_index);
			v = *(ptrV + nv_index);

			r = y + ((351 * (v - 128)) >> 8);  //r
			g = y - ((179 * (v - 128) + 86 * (u - 128)) >> 8); //g
			b = y + ((443 * (u - 128)) >> 8); //b

				r = image_clip_value(r, 0, 255);
			g = image_clip_value(g, 0, 255);
			b = image_clip_value(b, 0, 255);
			

			RGBBuf[rgb_index * 3 + 0] = b;
			RGBBuf[rgb_index * 3 + 1] = g;
			RGBBuf[rgb_index * 3 + 2] = r;

		}
	}

}


/**
* @brief   将YUV444p 图像转换 RGB888(内部函数)
* @param   [-ut] RGBBuf		输出的RGB图像数据
* @param   [in] pYUVBuf		输入的YUV444p图像数据BUFF
* @param   [in] YUVsize		输入的YUV444p图像数据BUFF大小
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV444P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
static int yuv444p_to_rgb888(unsigned char *RGBBuf, unsigned char  *pYUVBuf, unsigned int YUVsize, int w, int h, YUV444P_MODE_E mode)
{
	int  i = 0, j = 0;
	unsigned char *ptrY, *ptrU, *ptrV;
	unsigned char y, u, v;
	unsigned char r, g, b;
	unsigned int  nv_index = 0, rgb_index = 0;

	//---YUV444p存储V、U的两种方式区分:(每4个Y,公用一个U和V分量)
	ptrY = pYUVBuf;
	if (mode == YUV444P_I444)
	{
		ptrU = pYUVBuf + w*h;
		ptrV = ptrU + (w*h);
	}
	else if(mode == YUV444P_YV24)
	{
		ptrV = pYUVBuf + w*h;
		ptrU = ptrV + (w*h);
	}
	else
	{
		IMAGE_ERROR(" ------YUV444p mode dismatch !!!!!! ");
		return ERROR;
	}

	
	//---行扫描的方式
	for (i = 0; i < h; i++)
	{
		for (j = 0; j < w ; j++, rgb_index++ ) 
		{
			y = *(ptrY++);
			u = *(ptrU++);
			v = *(ptrV++);

			r = y + ((351 * (v - 128)) >> 8);  //r
			g = y - ((179 * (v - 128) + 86 * (u - 128)) >> 8); //g
			b = y + ((443 * (u - 128)) >> 8); //b

			r = image_clip_value(r, 0, 255);
			g = image_clip_value(g, 0, 255);
			b = image_clip_value(b, 0, 255);
			

			RGBBuf[rgb_index * 3 + 0] = b;
			RGBBuf[rgb_index * 3 + 1] = g;
			RGBBuf[rgb_index * 3 + 2] = r;

		}
	}

}



/**
* @brief   生成RGB24的图像
* @param   [in] filename	图像文件名 .rgb格式
* @param   [in] imageW		生成图像的宽度
* @param   [in] imageH		生成图像的高度
* @return  成功返回图像的大小
*/
int iamge_creat_rgb24(FILE *fp_rgb, int imageW, int imageH)
{
	int i = 0, imageSize = 0;
	unsigned char chr = 0;
	
	IMAGE_PTR_CHEAK(fp_rgb);

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	for (i = 0; i < imageW * imageH; i++)
	{
		if (i < imageW * imageH / 3)
		{
			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 255;
			fwrite(&chr, 1, 1, fp_rgb);
		}
		else if (i < imageW * imageH * 2 / 3)
		{
			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 255;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);
		}
		else
		{
			chr = 255;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);

			chr = 0;
			fwrite(&chr, 1, 1, fp_rgb);
		}


		imageSize++;
	}
	//---返回RGB 888 对应的大小 imageSize*3等价于w * h * 3
	return imageSize*3;	
}


/**
* @brief   rgb888 (rgb24)	转换为yuv420p
* @param   [in] fp_rgb			RGB图像文件句柄
* @param   [in] fp_yuv			YUV图像文件句柄
* @param   [in] imageW			生成图像的宽度
* @param   [in] imageH			生成图像的高度
* @param   [in] YUV420P_MODE_E	YUV420p的格式
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_rgb888_to_yuv420p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV420P_MODE_E YUVmode)
{
	unsigned char *pYUVBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}
	
	//---1、获取数据  (从开始位置读全部大小写入到转换函数RGB24_TO_YUV420P()的输入数组中)
	memset(s_uRGB, 0, sizeof(s_uRGB));
	fseek(fp_rgb, 0, SEEK_SET);
	iRet = fread(s_uRGB, 1, imageW * imageH * 3, fp_rgb);

	//---2、动态申请存放YUV的BUFF
	pYUVBuff = (unsigned char *)malloc(IMAGE_YUV420_SIZE(imageW, imageH)+1);
	if (pYUVBuff == NULL)
	{
		IMAGE_ERROR("malloc pYUVBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = rgb_to_yuv420p(pYUVBuff, imageW * imageH * 3 / 2, s_uRGB, imageW, imageH, YUVmode);
	if(iRet == ERROR)
	{
		IMAGE_ERROR("rgb_to_yuv420p failed !!!!!!!!!");
		free(pYUVBuff);
		return ERROR;
	}

	//---4、将YUV数据写入文件
	fseek(fp_yuv, 0, SEEK_SET);
	fwrite(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
		if (i % imageW == 0)
			printf("\n");
		printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pYUVBuff);
	return OK;
}

/**
* @brief   rgb888 (rgb24)	转换为yuv422p
* @param   [in] fp_rgb			RGB图像文件句柄
* @param   [in] fp_yuv			YUV图像文件句柄
* @param   [in] imageW			生成图像的宽度
* @param   [in] imageH			生成图像的高度
* @param   [in] YUV422P_MODE_E	YUV422p的格式
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_rgb888_to_yuv422p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV422P_MODE_E YUVmode)
{
	unsigned char *pYUVBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}

	//---1、获取数据  (从开始位置读全部大小写入到转换函数RGB24_TO_YUV420P()的输入数组中)
	memset(s_uRGB, 0, sizeof(s_uRGB));
	fseek(fp_rgb, 0, SEEK_SET);
	iRet = fread(s_uRGB, 1, imageW * imageH * 3, fp_rgb);		//--------------待优化!!!!!!!!!

	//---2、动态申请存放YUV的BUFF
	pYUVBuff = (unsigned char *)malloc(((unsigned int)IMAGE_YUV422_SIZE(imageW, imageH))+1);
	if (pYUVBuff == NULL)
	{
		IMAGE_ERROR("malloc pYUVBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = rgb_to_yuv422p(pYUVBuff, (unsigned int)IMAGE_YUV422_SIZE(imageW, imageH), s_uRGB, imageW, imageH, YUVmode);	//----待优化输入数据大小
	if (iRet == ERROR)
	{
		IMAGE_ERROR("rgb_to_yuv422p failed !!!!!!!!!");
		free(pYUVBuff);
		return ERROR;
	}

	//---4、将YUV数据写入文件
	fseek(fp_yuv, 0, SEEK_SET);
	fwrite(pYUVBuff, 1, imageW * imageH * 2, fp_yuv);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
	if (i % imageW == 0)
	printf("\n");
	printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pYUVBuff);
	return OK;
}

/**
* @brief   rgb888 (rgb24)	转换为yuv444p
* @param   [in] fp_rgb			RGB图像文件句柄
* @param   [in] fp_yuv			YUV图像文件句柄
* @param   [in] imageW			生成图像的宽度
* @param   [in] imageH			生成图像的高度
* @param   [in] YUV444P_MODE_E	YUV444p的格式
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_rgb888_to_yuv444p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV444P_MODE_E YUVmode)
{
	unsigned char *pYUVBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}

	//---1、获取数据  (从开始位置读全部大小写入到转换函数RGB24_TO_YUV444P()的输入数组中)
	memset(s_uRGB, 0, sizeof(s_uRGB));
	fseek(fp_rgb, 0, SEEK_SET);
	iRet = fread(s_uRGB, 1, imageW * imageH * 3, fp_rgb);		//--------------待优化!!!!!!!!!

	//---2、动态申请存放YUV的BUFF
	pYUVBuff = (unsigned char *)malloc(IMAGE_YUV444_SIZE(imageW, imageH)+1);
	if (pYUVBuff == NULL)
	{
		IMAGE_ERROR("malloc pYUVBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = rgb_to_yuv444p(pYUVBuff, imageW * imageH * 3, s_uRGB, imageW, imageH, YUVmode);
	if (iRet == ERROR)
	{
		IMAGE_ERROR("rgb_to_yuv422p failed !!!!!!!!!");
		free(pYUVBuff);
		return ERROR;
	}

	//---4、将YUV数据写入文件
	fseek(fp_yuv, 0, SEEK_SET);
	fwrite(pYUVBuff, 1, imageW * imageH * 3, fp_yuv);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
	if (i % imageW == 0)
	printf("\n");
	printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pYUVBuff);
	return OK;
}

/**
* @brief   yuv420p 转换为 rgb888 (rgb24)	
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV420P_MODE_E	输入图片的YUV420p的格式类型
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_yuv420p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV420P_MODE_E YUVmode)
{
	unsigned char *pRGBBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}

	//---1、获取数据  (从开始位置读全部大小写入到转换函数 yuv420p_to_rgb888() 的输入数组中)
	memset(s_uYUV, 0, sizeof(s_uYUV));
	fseek(fp_yuv, 0, SEEK_SET);
	iRet = fread(s_uYUV, 1, (uint32)(imageW * imageH * 3 / 2), fp_yuv);		//--------------待优化!!!!!!!!!

	//---2、动态申请存放RGB的BUFF
	pRGBBuff = (unsigned char *)malloc(imageW * imageH * 3 + 1);
	if (pRGBBuff == NULL)
	{
		IMAGE_ERROR("malloc pRGBBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = yuv420p_to_rgb888(pRGBBuff, s_uYUV, sizeof(s_uYUV), imageW, imageH, YUVmode);
	if (iRet == ERROR)
	{
		IMAGE_ERROR("yuv420p_to_rgb888 failed !!!!!!!!!");
		free(pRGBBuff);
		return ERROR;
	}

	//---4、将RGB数据写入文件
	fseek(fp_rgb, 0, SEEK_SET);
	fwrite(pRGBBuff, 1, imageW * imageH * 3, fp_rgb);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
	if (i % imageW == 0)
	printf("\n");
	printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pRGBBuff);
	return OK;
}

/**
* @brief   yuv422p 转换为 rgb888 (rgb24)	
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV422P_MODE_E	输入图片的YUV422p的格式类型
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_yuv422p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV422P_MODE_E YUVmode)
{
	unsigned char *pRGBBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}

	//---1、获取数据  (从开始位置读全部大小写入到转换函数 yuv420p_to_rgb888() 的输入数组中)
	memset(s_uYUV, 0, sizeof(s_uYUV));
	fseek(fp_yuv, 0, SEEK_SET);
	iRet = fread(s_uYUV, 1, imageW * imageH * 2, fp_yuv);		//--------------待优化!!!!!!!!!

	//---2、动态申请存放RGB的BUFF
	pRGBBuff = (unsigned char *)malloc(imageW * imageH * 3 + 1);
	if (pRGBBuff == NULL)
	{
		IMAGE_ERROR("malloc pRGBBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = yuv422p_to_rgb888(pRGBBuff, s_uYUV, sizeof(s_uYUV), imageW, imageH, YUVmode);
	if (iRet == ERROR)
	{
		IMAGE_ERROR("yuv422p_to_rgb888 failed !!!!!!!!!");
		free(pRGBBuff);
		return ERROR;
	}

	//---4、将RGB数据写入文件
	fseek(fp_rgb, 0, SEEK_SET);
	fwrite(pRGBBuff, 1, imageW * imageH * 3, fp_rgb);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
	if (i % imageW == 0)
	printf("\n");
	printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pRGBBuff);
	return OK;
}

/**
* @brief   yuv444p 转换为 rgb888 (rgb24)
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV444P_MODE_E	输入图片的YUV444p的格式类型
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_yuv444p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV444P_MODE_E YUVmode)
{
	unsigned char *pRGBBuff;
	int iRet = -1;
	unsigned int i = 0;

	if (imageW == 0 || imageH == 0)
	{
		IMAGE_ERROR("imageW = 0 or imageH = 0");
		return ERROR;
	}

	if (fp_rgb == NULL || fp_yuv == NULL)
	{
		IMAGE_ERROR("fp_rgb or fp_yuv open failed !!!!!!!");
		return ERROR;
	}

	//---1、获取数据  (从开始位置读全部大小写入到转换函数 yuv420p_to_rgb888() 的输入数组中)
	memset(s_uYUV, 0, sizeof(s_uYUV));
	fseek(fp_yuv, 0, SEEK_SET);
	iRet = fread(s_uYUV, 1, imageW * imageH * 3, fp_yuv);		//--------------待优化!!!!!!!!!

	//---2、动态申请存放RGB的BUFF
	pRGBBuff = (unsigned char *)malloc(imageW * imageH * 3 + 1);
	if (pRGBBuff == NULL)
	{
		IMAGE_ERROR("malloc pRGBBuff failed !!!!!!!!!");
		return ERROR;
	}

	//---3、调用对应转换函数
	iRet = yuv444p_to_rgb888(pRGBBuff, s_uYUV, sizeof(s_uYUV), imageW, imageH, YUVmode);
	if (iRet == ERROR)
	{
		IMAGE_ERROR("yuv444p_to_rgb888 failed !!!!!!!!!");
		free(pRGBBuff);
		return ERROR;
	}

	//---4、将RGB数据写入文件
	fseek(fp_rgb, 0, SEEK_SET);
	fwrite(pRGBBuff, 1, imageW * imageH * 3, fp_rgb);

	//---5、再次读文件,验证数据
	/*
	memset(pYUVBuff, 0, imageW * imageH * 3 / 2);
	fseek(fp_yuv, 0, SEEK_SET);
	fread(pYUVBuff, 1, imageW * imageH * 3 / 2, fp_yuv);
	for(i = 0; i < imageW * imageH * 3 / 2 ;i++)
	{
	if (i % imageW == 0)
	printf("\n");
	printf("%3d ", pYUVBuff[i]);
	}printf("\n");
	*/

	free(pRGBBuff);
	return OK;
}


3、处理函数头文件rgbtoyuv.h

#ifndef  _RGB_TO_YUV_H
#define  _RGB_TO_YUV_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define IMAGE_W		352		//---图像宽度
#define IMAGE_H		288		//---图像高度
#define IMAGE_CHAL	3		//---通道

#define ERROR -1
#define OK 0

typedef unsigned char uint8_t;
typedef unsigned int  uint32;


static unsigned char s_rgb[IMAGE_W][IMAGE_H][IMAGE_CHAL] = { 0 };
static unsigned char s_uRGB[IMAGE_W * IMAGE_H * IMAGE_CHAL] = { 0 };	/** <存放RGB图像数据的数组,用于RGB to YUV */
static unsigned char s_uYUV[IMAGE_W * IMAGE_H * IMAGE_CHAL] = { 0 };	/** <存放YUV图像数据的数组, 用于YUV to RGB */


typedef enum
{
	YUV420P_I420 = 0,	//I420 数据格式——YYYY U V
	YUV420P_YV12 = 1,	//YV12 数据格式——YYYY V U
}YUV420P_MODE_E;

typedef enum
{
	YUV422P_YU16 = 0,	//YU16 数据格式——YY U V
	YUV422P_YV16 = 1,	//YV16 数据格式——YY V U
}YUV422P_MODE_E;

typedef enum
{
	YUV444P_I444 = 0,	//I444 数据格式——YY UU VV
	YUV444P_YV24 = 1,	//YV24 数据格式——YY VV UU
}YUV444P_MODE_E;



/**
* @brief   生成RGB24的图像
* @param   [in] fp_rgb		图像文件名句柄
* @param   [in] imageW		生成图像的宽度
* @param   [in] imageH		生成图像的高度
* @return  成功返回图像的大小
*/
int iamge_creat_rgb24(FILE *fp_rgb, int imageW, int imageH);


/**
* @brief   将RGB24 图像转换 YUV420p  YUV数据(内部函数)
* @param   [in] fp_rgb		RGB图像文件句柄
* @param   [in] fp_yuv		YUV图像文件句柄s
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] mode		参考YUV420P_MODE_E 枚举变量
* @return  OK / ERROR 成功/失败
*/
int image_rgb888_to_yuv420p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV420P_MODE_E YUVmode);


/**
* @brief   rgb888 (rgb24)	转换为yuv422p
* @param   [in] fp_rgb		RGB图像文件句柄
* @param   [in] fp_yuv		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度s
* @param   [in] YUV422P_MODE_E	YUV422p的格式
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_rgb888_to_yuv422p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV422P_MODE_E YUVmode);


/**
* @brief   rgb888 (rgb24)	转换为yuv444p
* @param   [in] fp_rgb		RGB图像文件句柄
* @param   [in] fp_yuv		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV444P_MODE_E	YUV444p的格式
* @return  返回转换结果 OK/ERROR  成功/失败
*/
int image_rgb888_to_yuv444p(FILE *fp_rgb, FILE *fp_yuv, int imageW, int imageH, YUV444P_MODE_E YUVmode);


/**
* @brief   rgb888 (rgb24)	转换为yuv420p
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV420P_MODE_E	输入图片的YUV420p的格式类型
* @return  [return]OK or ERROR  	    返回转换结果成功 or 失败
*/
int image_yuv420p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV420P_MODE_E YUVmode);

/**
* @brief   rgb888 (rgb24)	转换为yuv422p
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV422P_MODE_E	输入图片的YUV422p的格式类型
* @return  [return]OK or ERROR  	    返回转换结果成功 or 失败
*/
int image_yuv422p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV422P_MODE_E YUVmode);

/**
* @brief   rgb888 (rgb24)	转换为yuv444p
* @param   [in] fp_yuv		RGB图像文件句柄
* @param   [in] fp_rgb		YUV图像文件句柄
* @param   [in] w			输入图像的宽度
* @param   [in] h			输入图像的高度
* @param   [in] YUV444P_MODE_E	输入图片的YUV444p的格式类型
* @return  [return]OK or ERROR  	    返回转换结果成功 or 失败
*/
int image_yuv444p_to_rgb888(FILE *fp_yuv, FILE *fp_rgb, int imageW, int imageH, YUV444P_MODE_E YUVmode);


#endif

4、Makefile 编译规则

app_main:rgbtoyuv.o app_main.o
        gcc -o app_main  rgbtoyuv.o app_main.o

app_main.o:app_main.c rgbtoyuv.h
        gcc -c app_main.c

rgbtoyuv.o:rgbtoyuv.c
        gcc -c rgbtoyuv.c

clean:
        rm *.yuv *.rgb app_main

执行方式

四文件在同级目录下,执行Makefile生成执行程序app_main :

make clean
make && ./app_main

执行结果

创建的RGB图像:

在这里插入图片描述

转换出来的YUV420_I420格式图像:

在这里插入图片描述

再次转换YUV —> RGB图像:

在这里插入图片描述

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
YUV422是一种颜色编码格式,它有多种存储方式。其一种是打包格式(Packed),即Y、U、V三个分量连续存储在一起,每个像素占16比特。另一种是平面格式(Planar),即Y、U、V分别存储在不同的内存块,其Y占据width*height的空间,而U和V合并占据width*height的空间。根据U、V的顺序,可以分为两种格式,U前V后的是YUV422P,也叫I422,V前U后的是YV16。还有一种变态的半平面格式(Semi-planar),即Y单独占一块内存,而U和V紧挨着排在一起,根据U、V的顺序,又有两种格式,U前V后的是NV16,V前U后的是NV61。\[1\] 要将YUV422换为RGB格式,可以使用OpenCV库的函数。首先,读取YUV格式的文件或模拟从设备获取YUV数据流。然后,使用相应的函数将YUV数据换为Mat格式的RGB图像。最后,将Mat类型的图像显示在QLabel控件上。可以在MainWindow的.cpp文件添加一个函数来实现将Mat类型图像显示在QLabel控件上的功能。该函数首先对图像进行处理,将其换为适合显示的格式,然后将其换为QPixmap对象,并将其设置为QLabel控件的图像。\[2\]\[3\] #### 引用[.reference_title] - *1* [YUV格式学习:YUV422P、YV16、NV16、NV61格式换成RGB24](https://blog.csdn.net/subfate/article/details/47304945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [YUV422RGB并显示于Qlabel](https://blog.csdn.net/xiaohuolong1827/article/details/123646367)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值