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);
}

在这里插入图片描述
这是YUV_I420图片
转换后的RGB8888是这样的:
在这里插入图片描述
• 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<unsigned char>(R);
        *(p_rgb++) = static_cast<unsigned char>(G);
        *(p_rgb++) = static_cast<unsigned char>(B);
        Y = *(p_y++);
        *(p_rgb++) = static_cast<unsigned char>(R);
        *(p_rgb++) = static_cast<unsigned char>(G);
        *(p_rgb++) = static_cast<unsigned char>(B);
    }
}

这是YUV422sp的图
在这里插入图片描述
转换为RGB后
在这里插入图片描述
• 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"<<endl;
    }
    nv12 = cv::Mat(HEIGHT * 3/2,WIDTH,CV_8UC1);
    fread(nv12.data,sizeof(unsigned char),HEIGHT*WIDTH*3/2,fp);
    fclose(fp);
    cvtColor(nv12,img,CV_YUV2RGB_NV12);
    cvtColor(img,img,CV_BGR2RGB);
    imshow("rgb",img);
}
void NV122RGBA(unsigned char* nv12,unsigned char* rgba)
{
    Mat Matnv12;
    Mat Matrgba;
    Matnv12 = cv::Mat(HEIGHT * 3/2,WIDTH,CV_8UC1);
    memcpy(Matnv12.data,nv12,HEIGHT*WIDTH*3/2);
    cvtColor(Matnv12,Matrgba,CV_YUV2RGBA_NV12);
    cvtColor(Matrgba,Matrgba,CV_BGRA2RGBA);
    memcpy(rgba,Matrgba.data,HEIGHT*WIDTH*4);
}
```
nv12是这样的

在这里插入图片描述
对应的RGB是这样的
在这里插入图片描述
• 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<unsigned short>(red&0xF8)<<8) + (static_cast<unsigned char>(green&0xFC)<<3)
                + (static_cast<unsigned short>(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"<<endl;
    }
    int imglength = WIDTH * HEIGHT * 4;
    unsigned char* img1 = new unsigned char[imglength];
    fread(img1,sizeof(unsigned char),imglength,fp);
    fclose(fp);
    fp = nullptr;

    fp = fopen(path2.c_str(),"rb+");
    if(!fp)
    {
        cout<<"Fail to open file"<<endl;
    }
    unsigned char* img2 = new unsigned char[imglength];
    fread(img2,sizeof(unsigned char),imglength,fp);
    fclose(fp);
    fp = nullptr;
    for(int i = 0;i < imglength;++i)
    {
        *(diff++) = max(static_cast<int>(*img1),static_cast<int>(*img2)) - min(static_cast<int>(*img1),static_cast<int>(*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"<<endl;
    }
    int imglength = WIDTH * HEIGHT * 4;
    unsigned char* img1 = new unsigned char[imglength];
    fread(img1,sizeof(unsigned char),imglength,fp);
    fclose(fp);
    fp = nullptr;
    memcpy(Matimg1.data,img1,HEIGHT*WIDTH*4);

    Mat Matimg2 = cv::Mat(HEIGHT,WIDTH,CV_8UC4);
    fp = fopen(path1.c_str(),"rb+");
    if(!fp)
    {
        cout<<"Fail to open file"<<endl;
    }
    unsigned char* img2 = new unsigned char[imglength];
    fread(img2,sizeof(unsigned char),imglength,fp);
    fclose(fp);
    fp = nullptr;
    memcpy(Matimg2.data,img2,HEIGHT*WIDTH*4);

    Mat Matdiff;
    cvtColor(Matimg1,Matimg1,CV_RGBA2GRAY);
    cvtColor(Matimg2,Matimg2,CV_RGBA2GRAY);
    absdiff(Matimg1,Matimg2,Matdiff);
    memcpy(diff,Matdiff.data,HEIGHT*WIDTH);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值