在图像处理、视频开发中,因为不同设备、不同平台、摄像头获取的原始数据都不一样,经常要完成颜色之间转换,下面列出一些常见的颜色格式转换代码。
比如:
Android系统的摄像头返回的图像格式NV21
X264编码需要的图像格式YUV420P
Linux下摄像头返回的图像格式一般是YUYV
GUI图形控件一般显示图片需要RGB数据
如果想查看原始的YUV图片windows下可以使用7yuv软件。
列出转换代码列表:
void YUV420P_to_RGB24(unsigned char *data, unsigned char *rgb, int width, int height);
void NV21_TO_RGB24(unsigned char *data, unsigned char *rgb, int width, int height);
void YUV420P_TO_RGB24(unsigned char *yuv420p, unsigned char *rgb24, int width, int height);
void yuyv_to_rgb(unsigned char *yuv_buffer,unsigned char *rgb_buffer,int iWidth,int iHeight);
int yuyv_to_yuv420p(const unsigned char *in, unsigned char *out, unsigned int width, unsigned int height);
void NV21_YUV420P(const unsigned char* image_src, unsigned char* image_dst,int image_width, int image_height);
bool RGB24_TO_YUV420(unsigned char *RgbBuf,int w,int h,unsigned char *yuvBuf)
核心代码: 下面是纯C代码,不依赖任何库,可以在任何平台复制粘贴移植调用
/*
函数功能: 将YUV数据转为RGB格式
函数参数:
unsigned char *yuv_buffer: YUV源数据
unsigned char *rgb_buffer: 转换之后的RGB数据
int iWidth,int iHeight : 图像的宽度和高度
*/
void VideoReadThread::yuyv_to_rgb(unsigned char *yuv_buffer,unsigned char *rgb_buffer,int iWidth,int iHeight)
{
int x;
int z=0;
unsigned char *ptr = rgb_buffer;
unsigned char *yuyv= yuv_buffer;
for (x = 0; x < iWidth*iHeight; x++)
{
int r, g, b;
int y, u, v;
if (!z)
y = yuyv[0] << 8;
else
y = yuyv[2] << 8;
u = yuyv[1] - 128;
v = yuyv[3] - 128;
r = (y + (359 * v)) >> 8;
g = (y - (88 * u) - (183 * v)) >> 8;
b = (y + (454 * u)) >> 8;
*(ptr++) = (r > 255) ? 255 : ((r < 0) ? 0 : r);
*(ptr++) = (g > 255) ? 255 : ((g < 0) ? 0 : g);
*(ptr++) = (b > 255) ? 255 : ((b < 0) ? 0 : b);
if(z++)
{
z = 0;
yuyv += 4;
}
}
}
// image_src是源图像,image_dst是转换后的图像
void VideoReadThread::NV21_YUV420P(const unsigned char* image_src, unsigned char* image_dst,int image_width, int image_height)
{
unsigned char* p = image_dst;
memcpy(p, image_src, image_width * image_height * 3 / 2);
const unsigned char *pNV = image_src + image_width * image_height;
unsigned char *pU = p + image_width * image_height;
unsigned char *pV = p + image_width * image_height + ((image_width * image_height)>>2);
for (int i=0; i<(image_width * image_height)/2; i++)
{
if((i%2)==0)
*pV++=*(pNV+i);
else
*pU++=*(pNV+i);
}
}
//YUYV==YUV422
int VideoReadThread::yuyv_to_yuv420p(const unsigned char *in, unsigned char *out, unsigned int width, unsigned int height)
{
unsigned char *y = out;
unsigned char *u = out + width*height;
unsigned char *v = out + width*height + width*height/4;
unsigned int i,j;
unsigned int base_h;
unsigned int is_u = 1;
unsigned int y_index = 0, u_index = 0, v_index = 0;
unsigned long yuv422_length = 2 * width * height;
//序列为YU YV YU YV,一个yuv422帧的长度 width * height * 2 个字节
//丢弃偶数行 u v
for(i=0; i 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(r < 0) r = 0;
if(g < 0) g = 0;
if(b < 0) b = 0;
index = rgb_index % width + (height - i - 1) * width;
//rgb[index * 3+0] = b;
//rgb[index * 3+1] = g;
//rgb[index * 3+2] = r;
//颠倒图像
//rgb[height * width * 3 - i * width * 3 - 3 * j - 1] = b;
//rgb[height * width * 3 - i * width * 3 - 3 * j - 2] = g;
//rgb[height * width * 3 - i * width * 3 - 3 * j - 3] = r;
//正面图像
rgb[i * width * 3 + 3 * j + 0] = b;
rgb[i * width * 3 + 3 * j + 1] = g;
rgb[i * width * 3 + 3 * j + 2] = r;
rgb_index++;
}
}
}
void VideoReadThread::YUV420P_TO_RGB24(unsigned char *yuv420p, unsigned char *rgb24, int width, int height) {
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int indexY = y * width + x;
int indexU = width * height + y / 2 * width / 2 + x / 2;
int indexV = width * height + width * height / 4 + y / 2 * width / 2 + x / 2;
u_char Y = yuv420p[indexY];
u_char U = yuv420p[indexU];
u_char V = yuv420p[indexV];
rgb24[index++] = Y + 1.402 * (V - 128); //R
rgb24[index++] = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128); //G
rgb24[index++] = Y + 1.772 * (U - 128); //B
}
}
}
unsigned char clip_value(unsigned char x,unsigned char min_val,unsigned char max_val){
if(x>max_val){
return max_val;
}else if(x> 8) + 16 ;
u = (unsigned char)( ( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128 ;
v = (unsigned char)( ( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128 ;
*(ptrY++) = clip_value(y,0,255);
if (j%2==0&&i%2 ==0){
*(ptrU++) =clip_value(u,0,255);
}
else{
if (i%2==0){
*(ptrV++) =clip_value(v,0,255);
}
}
}
}
return true;
}
下面公众号里有QT、C++、C、单片机的基础全套学习教程: