本篇文章僅介紹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: