图形图像基础知识(1)---- RGB/YUV 颜色格式

常见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 格式在屏幕上分布如下图所示:
YUV444.png

YUV422类型

每两个相邻像素点共用一对UV值,所以在1080x1920的图像中,需要1080x1920x(1Y+ 0.5U + 0.5V)(字节)来存储
YUV422格式在屏幕上分布如下图所示:
(所以 YUV422 类型所占字节数是 RGB/YUV444 类型的 2/3)
YUV422.png

YUV422 存储格式:

  • YUYV packed
    YUYV.png

  • YVYU packed
    YVYU.png

  • YU16、I422
    YU16.png

  • YV16
    YV16.png

YUV420类型

每四个相邻像素点共用一对UV 值,相当于每个Y只占用0.25U0.25V,在1080x1920的图像中,需要1080x1920x(1Y+ 0.25U + 0.25V)(字节)来存储
(YUV420 占用的大小是 RGB/YUV444 类型的一半,YUV420 类型可以概括为 UV 分量两行变一行,一行变一半)
YUV422 格式在屏幕上分布如下图所示:
YUV420.jpg

YU12(I420)、YV12
YU12-YV12.png

NV12 NV21
NV12-NV21.png

参考实例

这里将 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值