视频教程:YUV420和RGB相互转换--C++实现,二

我是Gem,今天做个简单的视频,我的耳机坏了,不好意思,没有声音,请原谅~~

时间很仓促,我把作业全部做完了,完整的过程我演示你看看,有什么问题请你指出来~~

详细的代码说明和友好的界面(用MFC做),即将给出,如果你感兴趣,请时刻关注我的Blog: http://hexun.com/ctfysj

我们开始,在C++ 里面我建立了两个工程,一个是RGB2YUV,另一个是yuv2rgb的,我们先看看RGB2YUV

看我操作~~~

RGB2YUV420 演示:

用的图片是你给我的test.bmp,把test.bmp文件拷到工程目录下 E:\网站文件夹\YUV420和RGB相互转换\homework\RGB2YUV

我转换成YUV420时候,存储在test.cif

看我生成这种文件啊~~

编译: 0 error(s), 0 warning(s)

这种效果可以吗? 应该还行吧~~

现在再看 RGB2YUV420 演示

RGB2YUV420 演示:

把上面生成的test.cif文件拷到工程目录下 E:\网站文件夹\YUV420和RGB相互转换\homework\yuv2rgb

还原成test.bmp文件

编译:0 error(s), 0 warning(s)

还原后,差不多吧,反正我没有看出来有什么区别~~

完整的代码 : 在 RGBYUV420代码完整版.txt 记事本里面

慕容听雨

个人主页:http://hexun.com/ctfysj

QQ:308463776

说明:下面的代码用C\C++执行都可以,用C的时候请把#include<iostream> 删除。

代码的详细说明视频即将推出,请时刻关注我的Blog: http://hexun.com/ctfysj

RGB to YUV420 原代码: RGB2YUV.CPP文件

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include<iostream>

//转换矩阵

#define MY(a,b,c) (( a* 0.2989 + b* 0.5866 + c* 0.1145))

#define MU(a,b,c) (( a*(-0.1688) + b*(-0.3312) + c* 0.5000 + 128))

#define MV(a,b,c) (( a* 0.5000 + b*(-0.4184) + c*(-0.0816) + 128))

//大小判断

#define DY(a,b,c) (MY(a,b,c) > 255 ? 255 : (MY(a,b,c) < 0 ? 0 : MY(a,b,c)))

#define DU(a,b,c) (MU(a,b,c) > 255 ? 255 : (MU(a,b,c) < 0 ? 0 : MU(a,b,c)))

#define DV(a,b,c) (MV(a,b,c) > 255 ? 255 : (MV(a,b,c) < 0 ? 0 : MV(a,b,c)))

//只处理352*288文件

#define WIDTH 352

#define HEIGHT 288

//读BMP

void ReadBmp(unsigned char *RGB,FILE *fp);

//转换函数

void Convert(unsigned char *RGB, unsigned char *YUV);

//入口

int main()

{

int i=1;

char file[255];

FILE *fp;

FILE *fp2;

unsigned char *YUV = NULL;

unsigned char *RGB = NULL;

unsigned int imgSize = WIDTH*HEIGHT;

if((fp2 = fopen("test.cif", "wb")) == NULL)//生成文件名

{

return 0;

}

RGB = (unsigned char*)malloc(imgSize*6);

YUV = (unsigned char*)malloc(imgSize + (imgSize>>1));

for(i=1; i<2; i++)

{

sprintf(file, "test.bmp", i);//读取文件

if((fp = fopen(file, "rb")) == NULL)

continue;

printf("打开文件%s\n", file);

ReadBmp(RGB, fp);

Convert(RGB, YUV);

fwrite(YUV, 1, imgSize+(imgSize>>1), fp2);//写入文件

fclose(fp);

}

fclose(fp2);

if(RGB)

free(RGB);

if(YUV)

free(YUV);

printf("完成\n");

system("pause");

return 1;

}

//读BMP

void ReadBmp(unsigned char *RGB,FILE *fp)

{

int i,j;

unsigned char temp;

fseek(fp,54, SEEK_SET);

fread(RGB+WIDTH*HEIGHT*3, 1, WIDTH*HEIGHT*3, fp);//读取

for(i=HEIGHT-1,j=0; i>=0; i--,j++)//调整顺序

{

memcpy(RGB+j*WIDTH*3,RGB+WIDTH*HEIGHT*3+i*WIDTH*3,WIDTH*3);

}

//顺序调整

for(i=0; (unsigned int)i < WIDTH*HEIGHT*3; i+=3)

{

temp = RGB[i];

RGB[i] = RGB[i+2];

RGB[i+2] = temp;

}

}

void Convert(unsigned char *RGB, unsigned char *YUV)

{

//变量声明

unsigned int i,x,y,j;

unsigned char *Y = NULL;

unsigned char *U = NULL;

unsigned char *V = NULL;

Y = YUV;

U = YUV + WIDTH*HEIGHT;

V = U + ((WIDTH*HEIGHT)>>2);

for(y=0; y < HEIGHT; y++)

for(x=0; x < WIDTH; x++)

{

j = y*WIDTH + x;

i = j*3;

Y[j] = (unsigned char)(DY(RGB[i], RGB[i+1], RGB[i+2]));

if(x%2 == 1 && y%2 == 1)

{

j = (WIDTH>>1) * (y>>1) + (x>>1);

//上面i仍有效

U[j] = (unsigned char)

((DU(RGB[i ], RGB[i+1], RGB[i+2]) +

DU(RGB[i-3], RGB[i-2], RGB[i-1]) +

DU(RGB[i -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +

DU(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);

V[j] = (unsigned char)

((DV(RGB[i ], RGB[i+1], RGB[i+2]) +

DV(RGB[i-3], RGB[i-2], RGB[i-1]) +

DV(RGB[i -WIDTH*3], RGB[i+1-WIDTH*3], RGB[i+2-WIDTH*3]) +

DV(RGB[i-3-WIDTH*3], RGB[i-2-WIDTH*3], RGB[i-1-WIDTH*3]))/4);

}

}

}

YUV420 to RGB 原代码: yuv2rgb.cpp文件

#include <stdio.h>

#include <stdlib.h>

#include <iostream>

#define WIDTH 352

#define HEIGHT 288

//转换矩阵

double YuvToRgb[3][3] = {1, 0, 1.4022,

1, -0.3456, -0.7145,

1, 1.771, 0};

//根据RGB三分量写BMP,不必关注

int WriteBmp(int width, int height, unsigned char *R,unsigned char *G,unsigned char *B, char *BmpFileName);

//转换函数

int Convert(char *file, int width, int height, int n)

{

//变量声明

int i = 0;

int temp = 0;

int x = 0;

int y = 0;

int fReadSize = 0;

int ImgSize = width*height;

FILE *fp = NULL;

unsigned char* yuv = NULL;

unsigned char* rgb = NULL;

unsigned char* cTemp[6];

char BmpFileName[256];

//申请空间

int FrameSize = ImgSize + (ImgSize >> 1);

yuv = (unsigned char *)malloc(FrameSize);

rgb = (unsigned char *)malloc(ImgSize*3);

//读取指定文件中的指定帧

if((fp = fopen(file, "rb")) == NULL)

return 0;

fseek(fp, FrameSize*(n-1), SEEK_CUR);

fReadSize = fread(yuv, 1, FrameSize, fp);

fclose(fp);

if(fReadSize < FrameSize)

return 0;

//转换指定帧 如果你不是处理文件 主要看这里

cTemp[0] = yuv; //y分量地址

cTemp[1] = yuv + ImgSize; //u分量地址

cTemp[2] = cTemp[1] + (ImgSize>>2); //v分量地址

cTemp[3] = rgb; //r分量地址

cTemp[4] = rgb + ImgSize; //g分量地址

cTemp[5] = cTemp[4] + ImgSize; //b分量地址

for(y=0; y < height; y++)

for(x=0; x < width; x++)

{

//r分量

temp = cTemp[0][y*width+x] + (cTemp[2][(y/2)*(width/2)+x/2]-128) * YuvToRgb[0][2];

cTemp[3][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);

//g分量

temp = cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) * YuvToRgb[1][1]

+ (cTemp[2][(y/2)*(width/2)+x/2]-128) * YuvToRgb[1][2];

cTemp[4][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);

//b分量

temp = cTemp[0][y*width+x] + (cTemp[1][(y/2)*(width/2)+x/2]-128) * YuvToRgb[2][1];

cTemp[5][y*width+x] = temp<0 ? 0 : (temp>255 ? 255 : temp);

}

//写到BMP文件中

sprintf(BmpFileName, "test.bmp", file, n);

WriteBmp(width, height, cTemp[3], cTemp[4], cTemp[5], BmpFileName);

free(yuv);

free(rgb);

return n;

}

//入口 没啥东西

void main()

{

int i=1;

// for( i=0; i<260; i++)

Convert("test.cif", WIDTH, HEIGHT, i);//调用上面的Convert,获取文件的第i帧

}

//写BMP 不必关注

int WriteBmp(int width, int height, unsigned char *R,unsigned char *G,unsigned char *B, char *BmpFileName)

{

int x=0;

int y=0;

int i=0;

int j=0;

FILE *fp;

unsigned char *WRGB;

unsigned char *WRGB_Start;

int yu = width*3%4;

int BytePerLine = 0;

yu = yu!=0 ? 4-yu : yu;

BytePerLine = width*3+yu;

if((fp = fopen(BmpFileName, "wb")) == NULL)

return 0;

WRGB = (unsigned char*)malloc(BytePerLine*height+54);

memset(WRGB, 0, BytePerLine*height+54);

//BMP头

WRGB[0] = 'B';

WRGB[1] = 'M';

*((unsigned int*)(WRGB+2)) = BytePerLine*height+54;

*((unsigned int*)(WRGB+10)) = 54;

*((unsigned int*)(WRGB+14)) = 40;

*((unsigned int*)(WRGB+18)) = width;

*((unsigned int*)(WRGB+22)) = height;

*((unsigned short*)(WRGB+26)) = 1;

*((unsigned short*)(WRGB+28)) = 24;

*((unsigned short*)(WRGB+34)) = BytePerLine*height;

WRGB_Start = WRGB + 54;

for(y=height-1,j=0; y >= 0; y--,j++)

{

for(x=0,i=0; x<width; x++)

{

WRGB_Start[y*BytePerLine+i++] = B[j*width+x];

WRGB_Start[y*BytePerLine+i++] = G[j*width+x];

WRGB_Start[y*BytePerLine+i++] = R[j*width+x];

}

}

fwrite(WRGB, 1, BytePerLine*height+54, fp);

free(WRGB);

fclose(fp);

return 1;

}

视频和代码下载地址:

ftp://ctfysj.kongjian.in:***@ctfysj.kongjian.in/视频教学文件/homework.rar

***是密码,为了隐私,不能告诉别人,如你需要,请回复邮箱

密码:

**** 本内容跟帖回复才可浏览 *****

文件名: homework.rar

下载链接: http://cachefile5.fs2you.com/zh-cn/download/d643ef1aee1a19187dd0850c5259e48d/homework.rar