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