前言
主要是参考雷神的代码,向雷神学习,加上自己的理解。
YUV420p介绍
YUV420p是一个平铺格式,也就是先存Y再U最后存V。Y与UV分量数量是4比1。
如下,一个8*3的YUV420p这样存储。
// Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8
// Y9 Y10 Y11 Y12 Y13 Y14 Y15 Y16
// U1 U2 U3 U4 V1 V2 V3 V4
//
也就是 Y1 Y2 Y9 Y10 是一个宏像素,共用U1和V1,以次推类。
由于一个像素分量占据一个字节。所以像素长乘宽就是Y分量的大小。U以及V分量由于4个共用一个所以大小是像素长乘宽的四分之一。
// y: x*y;
// u: x*y/4;
// v: x*y/4;
分离YUV420p
所以,雷神这样将一个YUV420p分离为3个分量的文件。先读取原文件的所有YUV分量。再依次将YUV写入不同的文件中。根据传入的NUM帧数,进行循环。应该注意的是,由于UV分量只有原像素的四分之一,所以得到的UV像素会减半。如256 * 256会变为128 * 128.
int simplest_yuv420_split(char *url, int w, int h,int num){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_420_y.y","wb+");
FILE *fp2=fopen("output_420_u.y","wb+");
FILE *fp3=fopen("output_420_v.y","wb+");
unsigned char *pic=(unsigned char *)malloc(w*h*3/2);
for(int i=0;i<num;i++){
fread(pic,1,w*h*3/2,fp);
//Y
fwrite(pic,1,w*h,fp1);
//U
fwrite(pic+w*h,1,w*h/4,fp2);
//V
fwrite(pic+w*h*5/4,1,w*h/4,fp3);
}
free(pic);
fclose(fp);
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
其他格式以及打包格式原理相同。
YUV亮度色度的调节
亮度色度包和度等都是通过调节Y,U,V等等分量进行调节。如下雷神的亮度减半
int simplest_yuv420_halfy(char *url, int w, int h, int num) {
FILE *fp;
fopen_s(&fp,url, "rb+");
FILE *fp1;
fopen_s(&fp1,"output_half.yuv", "wb+");
unsigned char *pic = (unsigned char *)malloc(w*h * 3 / 2);
for (int i = 0; i<num; i++) {
fread(pic, 1, w*h * 3 / 2, fp);
//Half
for (int j = w*h; j<w*h*5/4; j++) {
unsigned char temp = pic[j] +40;
//printf("%d,\n",temp);
pic[j] = temp;
}
fwrite(pic, 1, w*h * 3 / 2, fp1);
}
free(pic);
fclose(fp);
fclose(fp1);
return 0;
}
int main()
{
simplest_yuv420_halfy("sintel_480x272_yuv420p.yuv", 480,272, 125);
}