1、为什么要RGB转YUV(这位博主说的很清楚:https://www.cnblogs.com/zhengjianhong/p/7872459.html,我现在主要是用代码实现RGB转YUV)。
2、Rgb2Yuv.h
//RGB转YUV的数学公式
#define GetY(R, G, B) (unsigned char)(+0.2990 * R + 0.5870 * G + 0.1140 * B + 0)
#define GetU(R, G, B) (unsigned char)(-0.1687 * R - 0.3313 * G + 0.5000 * B + 128)
#define GetV(R, G, B) (unsigned char)(+0.5000 * R - 0.4187 * G - 0.0813 * B + 128)
class Rgb2Yuv
{
public:
Rgb2Yuv(void);
~Rgb2Yuv(void);
public:
/*******************************************
yuv422Planar format 数据排列:
Y0Y1Y2Y3....
U0U2U4....
V1V3V5....
********************************************/
void rgb2yuv422Planar(const unsigned char *rgbData, int width, int height, int widthstep, unsigned char*yuvData);
/*******************************
yuv422Packed format 数据排列:
Y0U0Y1V1Y2U2Y3V3.....
................
*******************************/
void rgb2yuv422Packed(const unsigned char *rgbData, int width, int height, int widthstep, unsigned char *yuvData);
};
3、Rgb2Yuv.cpp
#include "Rgb2Yuv.h"
#include
#include
#include
Rgb2Yuv::Rgb2Yuv(void)
{
}
Rgb2Yuv::~Rgb2Yuv(void)
{
}
/*******************************************
yuv422Planar format 数据排列:
Y0Y1Y2Y3....
U0U2U4....
V1V3V5....
********************************************/
void Rgb2Yuv::rgb2yuv422Planar(const unsigned char *rgbData, int width, int height, int widthstep, unsigned char*yuvData)
{
unsigned char temp = 0;
unsigned char *lineUV = (unsigned char *)malloc(width * sizeof(unsigned char));//偶数下标位存U,奇数下标位存V
if (NULL == lineUV)
{
perror("malloc lineUV memory failed!");
exit(1);
}
memset(lineUV, 0, sizeof(width * sizeof(unsigned char)));
for (int i = 0; i < height; i++)
{
for (int j = 0;j < width; j++) //y
{
unsigned char b = rgbData[i * widthstep + 3 * j];
unsigned char g = rgbData[i * widthstep + 3 * j + 1];
unsigned char r = rgbData[i * widthstep + 3 * j + 2];
unsigned char *y = yuvData + i * width + j;
temp = (int)GetY(r, g, b);
*y = (temp < 0) ? 0: ((temp > 255) ? 255 : temp);
if (0 == (j % 2))
{
temp = (int)GetU(r, g, b);
lineUV[j] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
}
else
{
temp = (int)GetV(r, g, b);
lineUV[j] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
}
}
for (int j = 0; j < width; j++) //u,v
{
if (0 == (j % 2)) //u
{
unsigned char *u = (yuvData + (height * width) + (i * width / 2) + (j / 2));
*u = lineUV[j];
}
else //v
{
unsigned char *v = (yuvData + (height * width * 3 / 2) + (i * width / 2) + (int)( j / 2));
*v = lineUV[j];
}
}
}
if (lineUV != NULL)
{
free(lineUV);
lineUV = NULL;
}
}
/*******************************
yuv422Packed format 数据排列:
Y0U0Y1V1Y2U2Y3V3.....
................
*******************************/
void Rgb2Yuv::rgb2yuv422Packed(const unsigned char *rgbData, int width, int height, int widthstep, unsigned char *yuvData)
{
int index = 0;
for (int y = 0; y < height; y++)
{
bool bsetU = true;
for (int x = 0; x < width; x++)
{
unsigned char b = rgbData[y * widthstep + 3 * x + 0];
unsigned char g = rgbData[y * widthstep + 3 * x + 1];
unsigned char r = rgbData[y * widthstep + 3 * x + 2];
yuvData[index++] = GetY(r, g, b);
yuvData[index++] = (bsetU ? GetU(r, g, b) : GetV(r, g, b));
bsetU = !bsetU;
}
}
}
4、main.cpp
#include
#include
#include
#include
#include
#include "Rgb2Yuv.h"
using namespace std;
int main(int argc, char *argv[])
{
//加载图片
IplImage *pSrc = cvLoadImage("./1.jpg", CV_LOAD_IMAGE_COLOR);
if (pSrc == NULL) return 0;
//把IplImage格式的RGB图片转成YUV422数据
int iSize = pSrc->width * pSrc->height * sizeof(char) * 3;
unsigned char *yuvData = new unsigned char[iSize];
memset(yuvData, 0, iSize);
//开始转换
Rgb2Yuv rgb;
rgb.rgb2yuv422Packed((const unsigned char*)pSrc->imageData, pSrc->width, pSrc->height, pSrc->widthStep, yuvData);
//把转换好数据写到文件
fstream outFile;
outFile.open("./1.yuv", ios::out);
outFile.write((const char*)yuvData, iSize);
outFile.close();
return 0;
}