目錄
- 常見RAW顏色格式
- RGB類型
- YUV類型
- YUV類型匯總
- YUV444類型
- YUV422類型
- YUV420類型
- 參考實例
常見RAW顏色格式
-
RGB 類型:
ARGB1010102,ABGR1010102,BGRA1010102,RGBA1010102
ARGB8888,ABGR8888,BGRA8888,RGBA8888
XRGB8888,XBGR8888,BGRX8888,RGBX8888
RGB888,BGR888
RGB565,BGR565 -
YUV 類型:
8-bit YUV 4:2:2 2-plane
8-bit YUV 4:2:2 1-plane(VYUY,YVYU)
8-bit YUV 4:2:0(2-plane)
8-bit YUV 4:2:0(3-plane)
RGB類型
RGB顏色空間以 R(Red:紅)、G(Green:綠)、B(Blue:藍) 三種基本色為基礎,進行不同程度的疊加,產生豐富而廣泛的顏色,所以俗稱三基色模式
不同的顏色格式表示的是各個分量占用的 BIT
數,比如 RGBA888
表示Red、Green、Blue、Alpha 通道各占 8BIT
,每個像素占 32BIT
(4字節)
YUV類型
YUV是一種顏色編碼方法,是編譯 true-color 顏色空間(color space)的種類,常使用在各個視頻處理組件中; YUV在對照片或視頻編碼時,考慮到人類的感知能力,允許降低色度的帶寬。其中的**“Y”**表示明亮度,也就是灰階值,即黑到白的范圍值,所以只有Y值的圖像是黑白的,U表示色彩值,V表示色彩的飽和度,UV用于指定像素的顏色
YUV類型匯總
YUV格式按照存儲方法可以分為下面兩類:
-
平面格式 (planar formats)
將Y、U、V的三個分量分別存放在不同的存儲空間中,先連續存儲所有像素點的Y,緊接著存儲所有像素點的U,隨后是所有像素點的V -
緊縮格式 (packed formats)
將Y、U、V值按照像素存儲在相同的存儲空間,和RGB的存放方式類似,每個像素點的Y,U,V是連續交替存儲的
按照采樣方式的不同,分為下面幾種類型
YUV4:4:4 表示完全取樣。
YUV4:2:2 表示2:1的水平取樣,垂直完全采樣。
YUV4:2:0 表示2:1的水平取樣,垂直2:1采樣。
YUV444類型
每個像素點都存儲對應的 YUV
值,注意 444 不是代表每個分量的字節數;YUV 每個分量都需要占用一個字節(8bit)
所以,在1080x1920
的圖像中,需要1080x1920x(1Y + 1U + 1V
(字節)來存儲
YUV 444 格式在屏幕上分布如下圖所示:
YUV422類型
每兩個相鄰像素點共用一對UV
值,所以在1080x1920的圖像中,需要1080x1920x(1Y+ 0.5U + 0.5V)(字節)來存儲
YUV422格式在屏幕上分布如下圖所示:
(所以 YUV422
類型所占字節數是 RGB
/YUV444
類型的 2/3)
YUV422 存儲格式:
-
YUYV packed
-
YVYU packed
-
YU16、I422
-
YV16
YUV420類型
每四個相鄰像素點共用一對UV
值,相當于每個Y只占用0.25U
和0.25V
,在1080x1920的圖像中,需要1080x1920x(1Y+ 0.25U + 0.25V)(字節)來存儲
(YUV420
占用的大小是 RGB/YUV444
類型的一半,YUV420
類型可以概括為 UV
分量兩行變一行,一行變一半)
YUV422
格式在屏幕上分布如下圖所示:
YU12(I420)、YV12
NV12 NV21
參考實例
這里將 RGB
類型轉換為 YUV
類型,展示了 YUV
類型的生成方法,注意:YUV
類型的寬高必須為偶數
void yuvImage::rgb2yuv(uint8_t r, uint8_t g, uint8_t b, uint8_t& y, uint8_t& u, uint8_t&v) {float y1 = 0.299*r + 0.587*g + 0.114*b;float u1 = -0.169*r - 0.331*g + 0.5*b + 128;float v1 = 0.5*r - 0.419*g - 0.081*b + 128;y = static_cast<uint8_t>(std::round(clamp(y1, 0.0f, 255.0f)));u = static_cast<uint8_t>(std::round(clamp(u1, 0.0f, 255.0f)));v = static_cast<uint8_t>(std::round(clamp(v1, 0.0f, 255.0f)));
}void yuvImage::rgb2nv12() {for(int y = 0; y < height; ++y) {for(int x = 0; x < width; ++x) {int idx = (height -1 -y)*width + x;int rgbidx = idx*3;uint8_t r = pixels[rgbidx+2];uint8_t g = pixels[rgbidx+1];uint8_t b = pixels[rgbidx];uint8_t yVal,uVal,vVal;rgb2yuv(r, g, b, yVal, uVal, vVal);yplane[y*width + x] = yVal;if(y%2 == 0 && x%2 == 0) {int uvIdx = (y/2)*(width/2) + x/2;uvplane[uvIdx*2] = uVal;uvplane[uvIdx*2+1] = vVal;}}}
}void yuvImage::save(const std::string& filename) {std::ofstream outFile(filename, std::ios::binary);if(!outFile.is_open()) {std::cerr << "fail to constuct file. " << std::endl;}outFile.write(reinterpret_cast<char*>(yplane.data()), yplane.size());outFile.write(reinterpret_cast<char*>(uvplane.data()), uvplane.size());std::cout << "save nv12 file " << filename << " success!." << std::endl;
}