C++实现RGB转Yuv422(在vs2010编写代码)

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

你可能感兴趣的:(图像处理算法)