RGB图片格式与YUV图片格式的相互转换

对于YUV图片和RGB565这类的图片,图片查看可以在网站http://rawpixels.net/上在线查看,不过需要的是原始数据,不能是压缩格式。
代码中有的部分使用的opencv,主要就是方便啦,老大说opencv也挺好,不要都自己造轮子,但为了理解图片格式,部分代码还是没有使用opencv的。
• 1:YUV420转RGBA8888

C++
//change yuvI420 to rgb8888
void yuvI4202RGB32(unsigned char* yuvI420,unsigned char* rgb32)
{
    Mat MatyuvI420 = cv::Mat(HEIGHT*3/2,WIDTH,CV_8UC1);
    memcpy(MatyuvI420.data,yuvI420,HEIGHT*WIDTH*3/2);
    Mat Matrgb32;
    cvtColor(MatyuvI420,Matrgb32,CV_YUV2RGBA_I420);
    memcpy(rgb32,Matrgb32.data,HEIGHT*WIDTH*4);
}

RGB图片格式与YUV图片格式的相互转换_第1张图片
这是YUV_I420图片
转换后的RGB8888是这样的:
RGB图片格式与YUV图片格式的相互转换_第2张图片
• 2:YUV422转RGBA8888

//YUV element to RGB
int YUV2R(int Y,int U,int V)
{
    int R = Y + 1.402*(V - 128);
    if(R < 0)
        return 0;
    else if(R > 255)
        return 255;
    else
        return R;
}
int YUV2G(int Y,int U,int V)
{
    int G = Y - 0.34414*(U - 128) - 0.71414*(V - 128);
    if(G < 0)
        return 0;
    else if(G > 255)
        return 255;
    else
        return G;
}
int YUV2B(int Y,int U,int V)
{
    int B = Y + 1.779*(U - 128);
    if(B < 0)
        return 0;
    else if(B > 255)
        return 255;
    else
        return B;
}

   
//422p
/*
 * yyyyyyyy
 * yyyyyyyy
 * uuuuuuuu
 * vvvvvvvv
*/
//yuyv
/*
 * yuyvyuyv
 * yuyvyuyv
 * yuyvyuyv
 * yuyvyuyv
*/
//change yuv422sp to rgb24;
/*
 * ----rgb----
 * (rgb)(rgb)(rgb)(rgb)
 * (rgb)(rgb)(rgb)(rgb)
 * (rgb)(rgb)(rgb)(rgb)
 * (rgb)(rgb)(rgb)(rgb)
*/
void yuv422sp2rgb24(unsigned char* yuv422sp,unsigned char* rgb24)
{
    int Y,U,V;
    int R,G,B;
    unsigned char* p_y;
    unsigned char* p_uv;
    unsigned char* p_rgb;
    p_y = yuv422sp;
    p_uv = p_y + WIDTH*HEIGHT;
    p_rgb = rgb24;
    for(int i = 0;i < WIDTH*HEIGHT/2;++i)
    {
        Y = *(p_y++);
        U = *(p_uv++);
        V = *(p_uv++);
        R = YUV2R(Y,U,V);
        G = YUV2G(Y,U,V);
        B = YUV2B(Y,U,V);
        *(p_rgb++) = static_cast(R);
        *(p_rgb++) = static_cast(G);
        *(p_rgb++) = static_cast(B);
        Y = *(p_y++);
        *(p_rgb++) = static_cast(R);
        *(p_rgb++) = static_cast(G);
        *(p_rgb++) = static_cast(B);
    }
}

这是YUV422sp的图
RGB图片格式与YUV图片格式的相互转换_第3张图片
转换为RGB后
RGB图片格式与YUV图片格式的相互转换_第4张图片
• 3:NV12转RGBA8888
NV12也是一种YUV420的图片,几种YUV420的格式

 * ----I420 yuv420p----
 * yyyyyyyy
 * yyyyyyyy
 * uuuuvvvv
 * ----YV12(yuv420)----
 * yyyyyyyy
 * yyyyyyyy
 * vvvvuuuu
 * ----NV12(yuv420)----
 * yyyyyyyy
 * yyyyyyyy
 * uvuvuvuv
`

//change NV12 to RGB format by using opencv
void NV122RGB(Mat& nv12,Mat& img,const string path)
{
    FILE *fp = nullptr;
    fp = fopen(path.c_str(),"rb+");
    if(!fp)
    {
        cout<<"Fail to open fail"<

RGB图片格式与YUV图片格式的相互转换_第5张图片
对应的RGB是这样的
RGB图片格式与YUV图片格式的相互转换_第6张图片
• 4:RGB565转RGBA888

//change rgb565 to rgb888
void rgb5652rgb888(unsigned short* rgb565,unsigned char* rgb888)
{
    int rgb565len = WIDTH*HEIGHT;
    for(int i = 0;i < rgb565len;++i)
    {
        unsigned short RGB565 = *rgb565;
        int r = ((RGB565 >> 11) & 0x1F);
        int g = ((RGB565 >> 5) & 0x3F);
        int b = ((RGB565) & 0x1F);
        r = ((r * 255) / 31) - 4;
        g = ((g * 255) / 63) - 2;
        b = ((b * 255) / 31) - 4;
        rgb888[i*3+0] = r;
        rgb888[i*3+1] = g;
        rgb888[i*3+2] = b;
        ++rgb565;
    }
}
//change rgb888 to rgb565
void rgb8882rgb565(unsigned char* rgb888,unsigned short* rgb565)
{
    int size = WIDTH*HEIGHT;
    for(int i = 0;i < size;++i)
    {
        unsigned short RGB565Color = 0;
        unsigned char red = rgb888[i*3+0];
        unsigned char green = rgb888[i*3+1];
        unsigned char blue = rgb888[i*3+2];
        rgb565[i] = (static_cast(red&0xF8)<<8) + (static_cast(green&0xFC)<<3)
                + (static_cast(blue&0xF8)>>3);
    }
}

RGB565在opencv上我也不清楚显示成啥样,反正show不出来,在rawpixels上验证过,代码是对的。
• 5:RGB888转RGBA8888

//change rgb888 to rgba
void rgb8882rgba(unsigned char* rgb888,unsigned char* rgba)
{
    Mat rgb;
    Mat rgb32;
    rgb = cv::Mat(HEIGHT,WIDTH,CV_8UC3);
    memcpy(rgb.data,rgb888,HEIGHT*WIDTH*3);
    cvtColor(rgb,rgb32,CV_RGB2RGBA);
    memcpy(rgba,rgb32.data,HEIGHT*WIDTH*4);
    //cvtColor(rgb888,rgba,CV_RGB2RGBA);
}

• 6:YUV的各种格式变换

//change yuv420 to yun422p
void yuv4202yuv422p(unsigned char* yuv420,unsigned char* yuv422)
{
    //copy Y element
    int Ylen = WIDTH * HEIGHT;
    memcpy(yuv422,yuv420,Ylen);
    //copy u element
    unsigned char* pU422 = yuv422 + Ylen;
    unsigned char* pU420 = yuv420 + Ylen;
    int Uwidth = WIDTH>>1;
    int Uheight = HEIGHT>>1;
    for(int y = 0;y < Uheight;++y)
    {
        memcpy(pU422+y*WIDTH,pU420+y*Uwidth,Uwidth);
        memcpy(pU422+y*WIDTH+Uwidth,pU420+y*Uwidth,Uwidth);
    }
    //copy v element
    unsigned char* pV422 = yuv422 + Ylen + (Ylen>>1);
    unsigned char* pV420 = pU420 + (Ylen>>2);
    int Vwidth = Uwidth;
    int Vheight = Uheight;
    for(int y = 0;y < Vheight;++y)
    {
        memcpy(pV422+y*WIDTH,pV420+y*Vwidth,Vwidth);
        memcpy(pV422+y*WIDTH+Vwidth,pV420+y*Vwidth,Vwidth);
    }
}
//change yuv422p to yuv422sp
//422sp
/*
 * yyyyyyyy
 * yyyyyyyy
 * uvuvuvuv
 * uvuvuvuv
*/
void yuv422p2yuv422sp(unsigned char* yuv422p,unsigned char* yuv422sp)
{
    int y_size;
    int uv_size;
    unsigned char* p_y1;
    unsigned char* p_uv;

    unsigned char* p_y2;
    unsigned char* p_u;
    unsigned char* p_v;

    y_size = uv_size = WIDTH*HEIGHT;
    p_y1 = yuv422p;
    p_y2 = yuv422sp;
    p_u = p_y1 + y_size;
    p_v = p_u + WIDTH*HEIGHT/2;
    p_uv = p_y2 + y_size;
    memcpy(p_y2,p_y1,y_size);
    for(int i = 0;i < uv_size/2;++i)
    {
        *(p_uv++) = *(p_u++);
        *(p_uv++) = *(p_v++);
    }
}

//422p
/*
 * yyyyyyyy
 * yyyyyyyy
 * uuuuuuuu
 * vvvvvvvv
*/
//yuyv
/*
 * yuyvyuyv
 * yuyvyuyv
 * yuyvyuyv
 * yuyvyuyv
*/
void yuv422p2yuyv(unsigned char* yuv422p,unsigned char* yuyv)
{
    int len = WIDTH*HEIGHT/2;
    int Ylen = WIDTH*HEIGHT;
    unsigned char* pU = yuv422p + Ylen;
    unsigned char* pV = pU + (Ylen>>2);
    for(int i = 0;i < len;++i)
    {
        *(yuyv++) = *(yuv422p++);
        *(yuyv++) = *(pU++);
        *(yuyv++) = *(yuv422p++);
        *(yuyv++) = *(pV++);
    }
}

• 7 检测图片差异

//get the difference of rgba img
void imgdiffrgba(string path1,string path2,unsigned char* diff)
{
    FILE *fp = nullptr;
    fp = fopen(path1.c_str(),"rb+");
    if(!fp)
    {
        cout<<"Fail to open file"<(*img1),static_cast(*img2)) - min(static_cast(*img1),static_cast(*img2));
        ++img1;
        ++img2;
    }
}
//get the difference by gray
void imgdiffgray(string path1,string path2,unsigned char* diff)
{
    Mat Matimg1 = cv::Mat(HEIGHT,WIDTH,CV_8UC4);
    FILE *fp = nullptr;
    fp = fopen(path1.c_str(),"rb+");
    if(!fp)
    {
        cout<<"Fail to open file"<

你可能感兴趣的:(实习项目)