对于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(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后
• 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"<
//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"<