现在的位置: 首页 > 综合 > 正文

关于YUV420转RGB24

2014年10月22日 ⁄ 综合 ⁄ 共 2938字 ⁄ 字号 评论关闭

        关于YUV的格式介绍,网上有很多相关的例子,这里介绍的主要是YUV420格式的图片文件转换为rgb24位图片的一个简单例子,至于后面拓展成视频的话个人认为是比较简单的,无非就是不断调用这个转码函数而已,这个程序是从之前网上下载的一个工程当中剥离出来的,关于这个简单例子,最主要的就是中间那部分的转换了,大家可以仔细看看,还有一点就是要好好了解一下YUV颜色空间和RGB颜色空间的具体概念,对理解代码也是很有帮助的,不过这个转码小例子的速度可能不是很高,因为要达到很高速率的话,就可以考虑采用汇编来写了,采用拓展指令集MMX来做,这种例子我们csdn网站就有人做出来了,大家可以搜一搜,作此文章用作笔记和广大程序员分享,如有什么建议或者错误的地方,欢迎大家指正,我们一起交流。

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

/*****************************************************************************
* 功  能:将一个double类型的数据转换成一个小于0 - 255 之间的无符号整型 

* 参  数:val  I  输入的double数据

* 返回值:转化后的unsigned char类型数据
*******************************************************************************/
unsigned char clip(double val)
{
	if (val > 255)
	{
		return 255;
	}
	else
		if (val < 0)
		{
			return 0;
		}
		else
		{
			return (unsigned char)val;
		}
}
/******************************************************************************
* 功  能:将YUV420文件转为RGB文件

* 参  数:rgb_data     O  存放转化后的RGB数据的缓冲区首地址
          yuv_data     I  存放转化前的YUV数据的缓冲区首地址
          image_width  I  图像的宽度
          image_height I  图像的高度
* 返回值:转化成功返回1,否则返回0
******************************************************************************/
int yuv420_2rgb(unsigned char *rgb_data, 
				 unsigned char *yuv_data, 
				 int            image_width, 
				 int            image_height)
{
	unsigned char y = 0;
	unsigned char u = 0;
	unsigned char v = 0;
	int           r = 0;
	int           g = 0;
	int           b = 0;

	int           c = 0;
	int           d = 0;
	int           e = 0;

	unsigned char *y_planar  = NULL;                       //指向Y平面的指针
	unsigned char *u_planar  = NULL;                       //指向U平面的指针
	unsigned char *v_planar  = NULL;                       //指向V平面的指针
	
    int           image_size = image_height * image_width; //图像的尺寸
	int           rgb_width;                               //RGB的宽度    
	int           u_width;                                 //U平面的宽度

	int           u_size;                                  //U平面的尺寸

	int           offset = 0;                              //偏移量

	int           i = 0;
	int           j = 0;

	u_size    = (image_size >> 2); //u平面的尺寸等于图像尺寸除以4

	y_planar  = yuv_data;	//	y分量
	u_planar  = yuv_data + image_size; //u分量= y分量偏移尺寸大小
	v_planar  = u_planar + u_size;//V分量=u分量偏移1/4尺寸大小
	rgb_width = image_width * 3;//rgb一行的数据宽度

	u_width   = (image_width >> 1);//U平面的宽度图像宽度除以2

	if ((rgb_data == NULL) || (yuv_data == NULL))
	{
		printf("the buffer is empty\n");
		return -1;
	}


	for (i = 0; i < image_height; i++)
	{
		for (j = 0; j < image_width; j++)
		{
			y = y_planar[image_width * i + j];
			offset = u_width * (i >> 1 ) + (j >> 1);
			u = u_planar[offset];
			v = v_planar[offset];
			c = y - 16;
			d = u - 128;
			e = v - 128;

			r = clip( (298 * c           + 409 * e  + 128) >> 8 );
			g = clip( (298 * c - 100 * d - 208 * e  + 128) >> 8 );
			b = clip( (298 * c + 516 * d            + 128) >> 8 );

			offset = rgb_width * (image_height - i -1) + j * 3;
			rgb_data[offset + 0] = b;
			rgb_data[offset + 1] = g ;
			rgb_data[offset + 2] = r;
		}
	}
	return 0;
}

int main(int argc, char *argv[])
{
	
	FILE *yuv = NULL;
	FILE *rgb = NULL;
	int height = 640;
	int wide = 480;
        int yuv_size = height*wide*3/2;
	int rgb_size = height*wide*3;
	unsigned char * rgb_data = NULL;
	int n = 0;
	unsigned char *yuv_buffer = NULL;
	yuv_buffer = (unsigned char *)malloc(sizeof(unsigned char)*yuv_size);
	rgb_data = (unsigned char*)malloc(sizeof(unsigned char)*rgb_size);

	if (yuv_buffer == NULL)
	{
		printf(" yuv_buffer malloc is fail\n");
		return 0;
	}
	
	if (rgb_data == NULL)
	{
		printf(" rgb_data malloc is fail\n");
		return 0;
	}
	if ((yuv=fopen(argv[1],"r"))== NULL)
	{
		printf("open yuv is fail\n");
		return 0;
	}
	if ((rgb=fopen(argv[2],"w"))== NULL)
	{
		printf("open rgb is fail\n");
		return 0;
	}
	n = fread(yuv_buffer,1,yuv_size,yuv);
	printf("n = [%d]\n",n);
    yuv420_2rgb(rgb_data,yuv_buffer,height,wide);
	n = fwrite(rgb_data,1,rgb_size,rgb);
	printf("n ===== [%d]\n",n);
	fclose(yuv);
	fclose(rgb);
	free(rgb_data);
	free(yuv_buffer);
    return 0;

}

抱歉!评论已关闭.