游戏开发者联盟

yuv420p编码格式

编码格式

Y'UV420p是平面格式。其原因是通过将U和V值分组在一起,图像变得更加可压缩。当给定Y'UV420p格式的图像数组时,先存储所有Y'值,然后是所有U值,最后是所有V值。

Y'V12格式与Y'UV420p基本上相同,但是它切换了U和V数据:Y'值后跟V值,最后是U值。只要注意从适当的位置提取U和V值,就可以使用相同的算法处理Y'UV420p和Y'V12。

与大多数Y'UV格式一样,Y'值与像素一样多。但是,U和V值只有四分之一。 U和V值分别对应于图像的2 x 2块,这意味着每个U和V条目均适用于四个像素。在Y'值之后,下一个X / 4索引是每个2 x 2块的U值,此后的下一个X / 4索引是V值,它们也适用于每个2 x 2块。

800px-Yuv420.svg (1)

如上图,前4行Y,每格代表一个像素,每个U或者V,依次对应四个像素,如上图箭头。每格存储为一个字节。
如果全部存到一个数组,U起始位置:x×y,V的起始位置: x×y + (x×y)/4。

YUV420P转rbg888

根据前面的yuv格式,我们可以提取到每个像素的 y u v值,然后输入到下面函数,就可以获取到rgb颜色。

void YUVImage::yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
        uint8_t *r, uint8_t *g, uint8_t *b) const {
    int rTmp = yValue + (1.370705 * (vValue-128));
    int gTmp = yValue - (0.698001 * (vValue-128)) - (0.337633 * (uValue-128));
    int bTmp = yValue + (1.732446 * (uValue-128));
    *r = clamp(rTmp, 0, 255);
    *g = clamp(gTmp, 0, 255);
    *b = clamp(bTmp, 0, 255);
}