当前位置: 首页 > 业余研究 > 正文

YUV格式学习:YUV444转换RGB24

YUV格式有很多种,按其采样方式,有444、422、420,还有411(但不常见)。针对数据的排序,又有平面格式和打包格式,还有“踢啊”特有的半平面格式——这些排列组合,就显得YUV格式多种多样,初看起来杂乱无章,但只要用心,就能理出头绪。像我,也是花了很多时间去慢慢搜索才真正理解。有时间会系统整理几篇文章出来,也会实践一下。
YUV444格式没有进行压缩,占用空间为with*height*3,与RGB占用空间相同。因此在转换上也很方便,但很多编码器似乎不太支持该格式。或许和其占用空间有莫大的关联吧。
首先给出生成查询表格的函数,代码是在网上找来的,如下:

#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif

static long U[256], V[256], Y1[256], Y2[256];

void init_yuv422p_table(void)
{
    int i;
    static int init = 0;
    if (init == 1) return;
    // Initialize table
    for (i = 0; i < 256; i++)
    { 
        V[i]  = 15938 * i - 2221300;
        U[i]  = 20238 * i - 2771300;
        Y1[i] = 11644 * i;
        Y2[i] = 19837 * i - 311710;
    }

    init = 1;
}

在转换成RGB之前,要调用上述函数。下面是YUV444转换成RGB24的函数实现:

void yuv4444_to_rgb24(unsigned char *yuv, unsigned char *rgb, int width, int height)
{
    int y, cb, cr;
    int r, g, b;
    int i = 0;
    unsigned char* p_y;
    unsigned char* p_u;
    unsigned char* p_v;
    unsigned char* p_rgb;

    p_y = yuv;
    p_u = yuv+width*height;
    p_v = yuv+2*width*height;
    p_rgb = rgb;

    init_yuv422p_table();

    for (i = 0; i < width * height; i++)
    {
        y  = p_y[0];
        cb = p_u[0];
        cr = p_v[0];
        //yuv2rgb(y, cb, cr, &r, &g, &b);
        //yuv2rgb_1(y, cb, cr, &r, &g, &b);
        r = MAX (0, MIN (255, (V[cr] + Y1[y])/10000));   //R value
        b = MAX (0, MIN (255, (U[cb] + Y1[y])/10000));   //B value
        g = MAX (0, MIN (255, (Y2[y] - 5094*(r) - 1942*(b))/10000)); //G value

        p_rgb[0] = r;
        p_rgb[1] = g;
        p_rgb[2] = b;;
        p_rgb += 3;
        p_y++;
        p_u++;
        p_v++;
    }
}

从代码看到,实际上就是扫描YUV444的内存,得到Y、U、V的分量,然后查表得到对应用R、G、B值,再赋值给RGB内存指针。如前所述,YUV444与RGB占用空间相同,故在代码并无太多的技巧。

李迟 2015.8.5 晚上


本文固定链接: http://www.latelee.org/my-study/yuv-learning-yuv444-to-rgb24.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: YUV格式学习:YUV444转换RGB24 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter