说明:下面的代码用C\C++执行都可以,用C的时候请把#include<iostream> 删除。
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;
- RGB = 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, 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;
- }