关于YUV420转RGB24

来源:互联网 发布:2016中国经济危机知乎 编辑:程序博客网 时间:2024/05/29 04:46

        关于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;}elseif (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平面的尺寸等于图像尺寸除以4y_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平面的宽度图像宽度除以2if ((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;}




0 0
原创粉丝点击