zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

Camera驱动 | YUV和RGB格式转化相关

驱动 格式 相关 转化 Camera rgb YUV
2023-06-13 09:13:49 时间

YUV、RGB格式转化相关

RGB色彩模式的分类

RGB的分类相较YUV来说就比较简单和直观,总体来说遵循“怎么取样就怎么存储的”分类方式

按照每个像素信息占据的空间分类,RGB格式可以分成以下几种:

RGB16:每个像素占据的空间是16bit

RGB16分类下还有两种细分类别:

RGB565:R\G\B分量分别占用5bit、6bit、5bit

可以用这几个掩码来分离RGB三个分量:

R = RGB & 0xF800

G = RGB & 0x07E0

B = RGB & 0x001F

RGB555:R\G\B分量分别占用5bit、5bit、5bit,留下最高位不用

可以用这几个掩码来分离RGB三个分量:

R = RGB & 0x7C00

G = RGB & 0x03E0

B = RGB & 0x001F

RGB24:每个像素占据的空间是24bit,其中R\G\B分量分别占用8bit、8bit、8bit

可以用这几个掩码来分离RGB三个分量:

R = RGB & 0x7C00

G = RGB & 0x03E0

B = RGB & 0x001F

RGB32:每个像素占据的空间是32bit,其中R\G\B分量分别占用8bit、8bit、8bit,多出的8bit用来存alpha分量,也就是透明分量

可以用这几个掩码来分离RGBA四个分量:

R = RGBA & 0x0000FF00

G = RGBA & 0x00FF0000

B = RGBA & 0xFF000000

A = RGBA & 0x000000FF

YUV420到RGB格式的转换

简单说完了RGB的储存原理和分类方式,接下来需要知道RGB和YUV各个分量的转化办法,这里直接给出转换公式:

R = Y + 1.402 * (V -128);

G = Y – 0.34414 * (U – 128) – 0.71414 * (V – 128);

B = Y + 1.772 * (U – 128);

由于YUV三个分量是有负数值的,而RGB分量的值都在0-255中间,所以需要将YUV分量进行量化

有上面的知识,加上之前对YUV的了解,下来就可以尝试将一张YUV420的图片转换成RGB888

void YUV420toRGB(unsigned char *yuv420, unsigned char*rgb ,int width, int height) {
    int Ylen = width * height;
    unsigned char *p_Y420 = yuv420;
    unsigned char *p_U420 = p_Y420 + Ylen;
    unsigned char *p_V420 = p_U420 + Ylen / 4;

    int rgbIndex = 0;
    int R,G,B,Y,U,V;
    for(int y = 0; y < height; y++) {
        for(int x = 0; x < width; x++){
            Y = *(p_Y420 + y * width + x);
            U = *(p_U420 + (y / 2) * (width / 2) + x / 2);
            V = *(p_V420 + (y / 2) * (width / 2) + x / 2);
            /* 
             * 在网络上搜索出的UV分量取值大多是 (y * width / 4) + x / 2这样
             * 我认为写成(y / 2) * (width / 2) + x / 2可以帮助理解
             * 原因如下:
             * 1.因为是YUV420的采样方式,每2×2个y分量公用一个u/v分量
             *   也就是对于偶数i,共用一个ui/vi的y分量有:
             *   yi    yi+1
             *   yi+w  yi+w+1
             *   所以在y和x方向分别需要/2
             * 2.width/2的原因是uv分量的行宽是y分量的一半
             *   y分量进入下一行需要+width个y分量
             *   那么uv分量进入下一行则需要+width/2个uv分量
             */
            R = Y + 1.402 * (V -128);
            G = Y - 0.34414 * (U - 128) - 0.71414 * (V - 128);
            B = Y + 1.772 * (U - 128);

            R = R < 255 ? R : 255;
            G = G < 255 ? G : 255;
            B = B < 255 ? B : 255;

            R = R < 0 ? 0 : R;
            G = G < 0 ? 0 : G;
            B = B < 0 ? 0 : B;

            *(rgb + rgbIndex++) = R;
            *(rgb + rgbIndex++) = G;
            *(rgb + rgbIndex++) = B;
        }
    }
}