各种RGB转YUV的计算

// 按照opencv数据存储格式,函数传参顺序为b、g、r      

void yuv2rgb_pixel(unsigned char b, unsigned char g, unsigned char r, unsigned char &y, unsigned char &u, unsigned char &v)
{
    //rgb转yuv公式,参考资料<a target=_blank href="http://www.cnblogs.com/dwdxdy/p/3713990.html">http://www.cnblogs.com/dwdxdy/p/3713990.html</a>
    y = 0.299 * r + 0.587 * g + 0.114 * b;
    u = -0.1687 * r - 0.3313 * g + 0.5 * b + 128;
    v = 0.5 * r - 0.4187 * g - 0.0813 * b + 128;
}

// rgb24转yuv422                                                        
void yuv2rgb_image(unsigned char *pRgb, unsigned char *pYuv, int width, int height)
{
    //考虑到每两个rgb像素对应一个yuyv组合,因此,width应为2的倍数
    int width1 = width = width / 2 * 2;

    for (int h = 0; h < height; h++)
    {
        unsigned char *ptr1 = pRgb + h * width * 3;
        unsigned char *ptr2 = pYuv + h * width * 2;

        for (int w = 0; w < width1; w += 2)
        {
            unsigned char y1, u1, v1, y2, u2, v2;
            yuv2rgb_pixel(*ptr1, *ptr1, *ptr1, y1, u1, v1);
            yuv2rgb_pixel(*ptr1, *ptr1, *ptr1, y2, u2, v2);
            //u、v分量取平均值
            unsigned char u = (u1 + u2) / 2;
            unsigned char v = (v1 + v2) / 2;
            *ptr2 = y1;
            *ptr2 = u;
            *ptr2 = y2;
            *ptr2 = v;
        }
    }
}

#define GetY(R,G,B) (0.257*(R)+0.504*(G)+0.98*(B)+16)
#define GetU(R,G,B) (0.148*(R)-0.291*(G)+0.439*(B)+128)
#define GetV(R,G,B) (0.439*(R)-0.368*(G)-0.071*(B)+128)

/*******************************************
yuv422Planar format 数据排列:
Y0Y1Y2Y3....
U0U2U4....
V1V3V5....
********************************************/
void  rgb2yuv422Planar(const unsigned char *rgbData, int height, int width, int widthstep, unsigned char*yuvData)
{
    int i, j, temp;
    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 (i = 0; i < height; i++)
    {
        for (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 (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;
    }


}
int  yuv422Packed2Planar(const unsigned char *packedData, unsigned char *planarData, int heigh, int width)
{
    int index;
    int i = 0;
    int j = 0;
    int k = 0;
    unsigned char *y = planarData;
    unsigned char *u = planarData + heigh * width;
    unsigned char *v = planarData + heigh * width * 3 / 2;
    bool flag = true;
    for (index = 0; index < 2 * width*heigh;)
    {
        y[i++] = packedData[index++];
        if (flag)
        {
            u[j++] = packedData[index++];
            flag = false;
        }
        else
        {
            v[k++] = packedData[index++];
            flag = true;
        }
    }
    if (2 * width*heigh == index && width*heigh == i && width*heigh / 2 == j && j == k)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

/*******************************
yuv422Packed format 数据排列:
Y0U0Y1V1Y2U2Y3V3.....
................
*******************************/
void  rgb2yuv422Packed(const unsigned char *rgbData, int height, int width, int widthstep, unsigned char *yuvData)
{
    int i, j, temp;
    int index = 0;

    for (i = 0; i < height; i++)
    {
        bool bsetU = true;
        for (j = 0; j < width; j++)
        {
            unsigned char r = rgbData[i*widthstep + 3 * j];
            unsigned char g = rgbData[i*widthstep + 3 * j + 1];
            unsigned char b = rgbData[i*widthstep + 3 * j + 2];
            temp = (int)GetY(r, g, b);
            yuvData[index++] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
            if (bsetU) //
            {
                temp = (int)GetU(r, g, b);
                yuvData[index++] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
                bsetU = false;
            }
            else
            {
                temp = (int)GetV(r, g, b);
                yuvData[index++] = (temp < 0) ? 0 : ((temp > 255) ? 255 : temp);
                bsetU = true;
            }
        }
    }

}


//************************************
// Method:    rgb24_to_yuv420p
// FullName:  rgb24_to_yuv420p
// Access:    public 
// Returns:   int            返回值为0表示成功,否则失败
// Qualifier:                将RGB24格式图像转化为YUV420P格式,并进行相应的缩放
// Parameter: void * src    输入缓冲
// Parameter: int srcW        源宽
// Parameter: int srcH        源高
// Parameter: int srcSz        输入RGB图像数据大小=srcW*srcH*3
// Parameter: void * dst    输出缓冲
// Parameter: int dstW        目标宽
// Parameter: int dstH        目标高
// Parameter: int dstSz        输出的YUV图像数据大小=dstW*dstH*1.5
//************************************
int rgb24_to_yuv420p(void* src, int srcW, int srcH, int srcSz, void* dst, int dstW, int dstH, int dstSz)
{
    if (!src || !dst || srcSz <= 0 || srcW <= 0 || srcH <= 0 || dstSz <= 0 || dstW <= 0 || dstH <= 0)
    {
        return -1;
    }
    if (srcSz != srcW * srcH * 3 || dstSz != dstW * dstH*1.5)
    {
        return -1;
    }
    auto* ctxt = sws_getContext(srcW, srcH, AV_PIX_FMT_BGR24, dstW, dstH, AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
    const int srcStride[1] = { 3 * srcW };
    const int dstStride[4] = { dstW, dstW / 2, dstW / 2, 0 };
    uint8_t * dstEx[4] = { 0 };
    dstEx[0] = (uint8_t *)dst;
    dstEx[1] = dstEx[0] + dstW * dstH;
    dstEx[2] = dstEx[1] + dstW * dstH / 4;
    sws_scale(ctxt, (const uint8_t * const *)&src, srcStride, 0, srcH, dstEx, dstStride);
    sws_freeContext(ctxt);
    return 0;
}

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 < min_val) {
        return min_val;
    }
    else {
        return x;
    }
}

//RGB to YUV420
bool RGB24_TO_YUV420(unsigned char *RgbBuf, int w, int h, unsigned char *yuvBuf)
{
    unsigned char*ptrY, *ptrU, *ptrV, *ptrRGB;
    memset(yuvBuf, 0, w*h * 3 / 2);
    ptrY = yuvBuf;
    ptrU = yuvBuf + w * h;
    ptrV = ptrU + (w*h * 1 / 4);
    unsigned char y, u, v, r, g, b;
    for (int j = 0; j < h; j++) {
        ptrRGB = RgbBuf + w * j * 3;
        for (int i = 0; i < w; i++) {

            r = *(ptrRGB++);
            g = *(ptrRGB++);
            b = *(ptrRGB++);
            y = (unsigned char)((66 * r + 129 * g + 25 * b + 128) >> 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;
}

在网上搜集的,方便以后,说不定以后用的上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值