YUV420 和RGB之间的转换的程序,YUV采样频率采用cif
2008-05-12 18:52
453 查看
YUV420 和RGB之间的转换的程序。
测试使用的cif文件:http://trace.eas.asu.edu/yuv/tempete.zip
【C/C++ code】 #include<stdio.h> #include<stdlib.h>
#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, unsignedchar *R,unsignedchar *G,unsignedchar *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;
unsignedchar* yuv= NULL;
unsignedchar* rgb= NULL;
unsignedchar* cTemp[6];
char BmpFileName[256];
//申请空间
int FrameSize= ImgSize+ (ImgSize>> 1);
yuv= (unsignedchar *)malloc(FrameSize); rgb= (unsignedchar *)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,"%s%05d.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("tempete.cif", WIDTH, HEIGHT, i);//获取文件的第i帧
}
//写BMP int WriteBmp(int width,int height, unsignedchar *R,unsignedchar *G,unsignedchar *B,char *BmpFileName)
{
int x=0;
int y=0;
int i=0;
int j=0;
FILE*fp;
unsignedchar *WRGB;
unsignedchar *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= (unsignedchar*)malloc(BytePerLine*height+54);
memset(WRGB,0, BytePerLine*height+54);
//BMP头
WRGB[0]= 'B';
WRGB[1]= 'M';
*((unsignedint*)(WRGB+2))= BytePerLine*height+54;
*((unsignedint*)(WRGB+10))= 54;
*((unsignedint*)(WRGB+14))= 40;
*((unsignedint*)(WRGB+18))= width;
*((unsignedint*)(WRGB+22))= height;
*((unsignedshort*)(WRGB+26))= 1;
*((unsignedshort*)(WRGB+28))= 24;
*((unsignedshort*)(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;
}
[/code]
测试使用的cif文件:http://trace.eas.asu.edu/yuv/tempete.zip
【C/C++ code】 #include<stdio.h> #include<stdlib.h>
#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, unsignedchar *R,unsignedchar *G,unsignedchar *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;
unsignedchar* yuv= NULL;
unsignedchar* rgb= NULL;
unsignedchar* cTemp[6];
char BmpFileName[256];
//申请空间
int FrameSize= ImgSize+ (ImgSize>> 1);
yuv= (unsignedchar *)malloc(FrameSize); rgb= (unsignedchar *)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,"%s%05d.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("tempete.cif", WIDTH, HEIGHT, i);//获取文件的第i帧
}
//写BMP int WriteBmp(int width,int height, unsignedchar *R,unsignedchar *G,unsignedchar *B,char *BmpFileName)
{
int x=0;
int y=0;
int i=0;
int j=0;
FILE*fp;
unsignedchar *WRGB;
unsignedchar *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= (unsignedchar*)malloc(BytePerLine*height+54);
memset(WRGB,0, BytePerLine*height+54);
//BMP头
WRGB[0]= 'B';
WRGB[1]= 'M';
*((unsignedint*)(WRGB+2))= BytePerLine*height+54;
*((unsignedint*)(WRGB+10))= 54;
*((unsignedint*)(WRGB+14))= 40;
*((unsignedint*)(WRGB+18))= width;
*((unsignedint*)(WRGB+22))= height;
*((unsignedshort*)(WRGB+26))= 1;
*((unsignedshort*)(WRGB+28))= 24;
*((unsignedshort*)(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;
}
【C/C++ code:RGB2YUV420 ,存储格式为cif】 #include <stdio.h> #include <stdlib.h> #include <string.h> //转换矩阵 #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("CIF文件", "wb")) == NULL) { return 0; } RGB = (unsigned char*)malloc(imgSize*6); YUV = (unsigned char*)malloc(imgSize + (imgSize>>1)); for(i=1; i<=260; i++) { sprintf(file, "RGB_%05d.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); } } }[code]
[/code]
相关文章推荐
- YUV420 和RGB之间的转换的程序
- YUV格式、RGB格式、JPEG格式、MJPEG格式之间的转换(C程序)之一
- 使用ffmpeg进行图像格式转换以及图像缩放/sws_scale/linux/c++/c/rgb-yuv420
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高) 这段时间一直在搞视频格式的转换问题,终于最近将一个图片的YUV
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- YUV、RGB和YCbCr之间的转换
- RGB和YUV之间转换
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- RGB与YUV之间的转换
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 解析yuv420图片并转换成RGB显示
- RGB颜色空间与YUV等颜色空间之间的转换单元
- 使用ffmpeg进行图像格式转换以及图像缩放/sws_scale/linux/c++/c/rgb-yuv420
- 关于YUV和RGB之间的转换公式
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- YUY2(YUV) 与 RGB 格式说明及转换程序