您的位置:首页 > 其它

YUV422P、YV16、NV16、NV61格式转换成RGB24

2017-01-20 15:34 453 查看
YUV422有打包格式(Packed),一如前文所述。同时还有平面格式(Planar),即Y、U、V是分开存储的,每个分量占一块地方,其中Y为width*height,而U、V合占width*height,该种格式每个像素占16比特。根据U、V的顺序,分出2种格式,U前V后即YUV422P,也叫I422,V前U后,叫YV16(YV表示Y后面跟着V,16表示16bit)。另外,还有一种变态的半平面格式(Semi-planar),即Y单独占一块地方,但其后U、V又紧挨着排在一起,根据U、V的顺序,又有2种,U前V后叫NV16,在国内好像很多人叫它为YUV422SP格式;V前U后叫NV61。不过这种格式似乎不太受VLC欢迎(具体可去看看VLC的wiki)。

先给出YUV422平面格式的转换函数,如下:

[cpp] view
plain copy

/** 

内存分布 

                    w 

            +--------------------+ 

            |Y0Y1Y2Y3...         | 

            |...                 |   h 

            |...                 | 

            |                    | 

            +--------------------+ 

            |U0U1      | 

            |...       |   h 

            |...       | 

            |          | 

            +----------+ 

            |V0V1      | 

            |...       |  h 

            |...       | 

            |          | 

            +----------+ 

                w/2 

*/  

void yuv422p_to_rgb24(YUV_TYPE type, unsigned char* yuv422p, 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 = yuv422p;  

    p_u = p_y + width * height;  

    p_v = p_u + width * height / 2;  

  

    if (type == FMT_YV16)  

    {  

        p_v = p_y + width * height;  

        p_u = p_u + width * height / 2;  

    }  

    p_rgb = rgb;  

  

    init_yuv422p_table();  

  

    for (i = 0; i < width * height / 2; i++)  

    {  

        y  = p_y[0];  

        cb = p_u[0];  

        cr = p_v[0];  

  

        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  

  

        // 此处可调整RGB排序,BMP图片排序为BGR  

        // 默认排序为:RGB  

        p_rgb[0] = r;  

        p_rgb[1] = g;  

        p_rgb[2] = b;  

  

        y  = p_y[1];  

        cb = p_u[0];  

        cr = p_v[0];  

        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[3] = r;  

        p_rgb[4] = g;  

        p_rgb[5] = b;  

  

        p_y += 2;  

        p_u += 1;  

        p_v += 1;  

        p_rgb += 6;  

    }  

}  



接着给出NV16、NV61转换成RGB的函数,如下:

[cpp] view
plain copy

/** 

内存分布 

                    w 

            +--------------------+ 

            |Y0Y1Y2Y3...         | 

            |...                 |   h 

            |...                 | 

            |                    | 

            +--------------------+ 

            |U0V0U1V1            | 

            |...                 |   h 

            |...                 | 

            |                    | 

            +--------------------+ 

                w/2 

UV交织为NV16,VU交织为NV61 

可以与上一函数合并,但方便查看,还是不合并 

*/  

void yuv422sp_to_rgb24(YUV_TYPE type, unsigned char* yuv422sp, 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_uv;  

    unsigned char* p_rgb;  

  

    p_y = yuv422sp;  

    p_uv = p_y + width * height;    // uv分量在Y后面  

    p_rgb = rgb;  

  

    init_yuv422p_table();  

  

    for (i = 0; i < width * height / 2; i++)  

    {  

        y  = p_y[0];  

        if (type ==  FMT_NV16)  

        {  

            cb = p_uv[0];  

            cr = p_uv[1];    // v紧跟u,在u的下一个位置  

        }  

        if (type == FMT_NV61)  

        {  

            cr = p_uv[0];  

            cb = p_uv[1];    // u紧跟v,在v的下一个位置  

        }  

  

        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  

  

        // 此处可调整RGB排序,BMP图片排序为BGR  

        // 默认排序为:RGB  

        p_rgb[0] = r;  

        p_rgb[1] = g;  

        p_rgb[2] = b;  

  

        y  = p_y[1];  

        if (type ==  FMT_NV16)  

        {  

            cb = p_uv[0];  

            cr = p_uv[1];  

        }  

        if (type ==  FMT_NV61)  

        {  

            cr = p_uv[0];  

            cb = p_uv[1];  

        }  

  

        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[3] = r;  

        p_rgb[4] = g;  

        p_rgb[5] = b;  

  

        p_y += 2;  

        p_uv += 2;  

        p_rgb += 6;  

    }  

}  

参考资料:

http://www.fourcc.org/yuv.php

https://wiki.videolan.org/YUV/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: