关于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;
}