本篇文章仅介绍YUV444、YUV422、YUV420等使用比较频繁的格式
简介:
YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
历史:
Y'UV的发明是由于彩色电视与黑白电视的过渡时期。黑白视频只有Y(Luma,Luminance)视频,也就是灰阶值。到了彩色电视规格的制定,是以YUV/YIQ的格式来处理彩色电视图像,把UV视作表示彩度的C(Chrominance或Chroma),如果忽略C信号,那么剩下的Y(Luma)信号就跟之前的黑白电视频号相同,这样一来便解决彩色电视机与黑白电视机的兼容问题。Y'UV最大的优点在于只需占用极少的带宽。
YUV颜色空间分布:
如果一个图像的宽和高已经确定,那么对于转换后的YUV各个格式的字节占用如下:
YUV444:表示每一个Y对应一个UV分量(如图),那么YUV对应的个数相同,YUV444所占用空间:即编码字节空间为=宽*高*3 (Y = U = V 宽高均相等)
YUV422:表示每两个Y对应一个UV分量,那么Y的个数是UV的个数*2,YUV422那么所占空间:即编码字节空间为=(Y)宽*高 + (U)宽*高*1/2 + (V)宽*高*1/2 = 宽*高*2 (Y宽 = 2*U宽 = 2*V宽,高度YUV相同)
YUV420:表示每4个Y对应一个UV分量,那么Y的个数是UV的个数*4,YUV420那么所占空间:即编码字节空间为=(Y)宽*高 + (U)宽*高*1/4 * (V)宽*高*1/4 = 宽*高*3/2 (Y宽高均为UV宽高的两倍)
分析:
编写C代码分别对各个格式进行读写分析,其中需要把YUV的每个分量保存为Y分量文件 ,此时需要YUV播放的软件,暂时使用YUV player
1:先用ffmpeg转换出3中格式的文件(本文使用图片进行测试:相当于一帧的视频)
网络获取一张图片,使用ffmpeg生成3种格式的YUV文件,命令如下:
ffmpeg -i test.jpg -pix_fmt yuv444p test_444.yuv ffmpeg -i test.jpg -pix_fmt yuv422p test_422.yuv ffmpeg -i test.jpg -pix_fmt yuv420p test_420.yuv
2:用C代码读取并分别分离出各个文件的Y、U、V分量文件:
enum YUVTYPE { YUV444, YUV422, YUV420 }; void read_split_yuvfile(const char* file, int width, int heiht, YUVTYPE yuvtype, int frames) { FILE* yuvFp = fopen(file, "rb+"); FILE* yFp = fopen("E:\\test_y.y", "wb+"); FILE* uFp = fopen("E:\\test_u.y", "wb+"); FILE* vFp = fopen("E:\\test_v.y", "wb+"); unsigned char* buf = NULL; int size = width * heiht; if (YUV444 == yuvtype) buf = (unsigned char*)malloc(size * 3); else if (YUV422 == yuvtype) buf = (unsigned char*)malloc(size << 1); else buf = (unsigned char*)malloc(size * 3 >> 1); for (int i = 0; i < frames; i++) { if (YUV444 == yuvtype) { fread(buf, 1, size * 3, yuvFp); fwrite(buf, 1, size, yFp); fwrite(buf + size, 1, size, uFp); fwrite(buf + (size << 1), 1, size, vFp); } else if (YUV422 == yuvtype) { fread(buf, 1, size << 1, yuvFp); fwrite(buf, 1, size, yFp); fwrite(buf + size, 1, size >> 1, uFp); fwrite(buf + (size * 3 >> 1), 1, size >> 1, vFp); } else { fread(buf, 1, size * 3 >> 1, yuvFp); fwrite(buf, 1, size, yFp); fwrite(buf + size, 1, size >> 2, uFp); fwrite(buf + (size * 5 >> 2), 1, size >> 2, vFp); } } free(buf); buf = NULL; fclose(yuvFp); fclose(yFp); fclose(uFp); fclose(vFp); }
生成文件大小与YUV的分量比相同,YUV444为1:1:1 YUV422为2:1:1 YUV420为4:1:1
由于压缩比较高,所以YUV420使用的比较多,YUV分量图示如下:
Y:
U:
V: