音视频数据处理入门:rgb与yuv相互转换

yuv240p的存储格式是planar,而rgb24的存储格式是packed

同样表示4个像素点:
yuv --> yyyy u v  = 6字节
rgb --> (r,g,b)*4 = 12字节

1、rgb --> yuv

Y= ( 66R + 129G + 25B)>>8 + 16

U= (-38R - 74G + 112B)>>8 +128

V= (112R - 94G - 18B)>>8 + 128

代码:

unsigned char clip_0_255(int val) {
    if (val < 0) return 0;
    else if (val > 255) return 255;
    return (unsigned char)val;
}

void data_conversion(unsigned char *rgbbuf, int w, int h, unsigned char *yuvbuf) {
    unsigned char *pY = yuvbuf;
    unsigned char *pU = yuvbuf + w*h;
    unsigned char *pV = pU + w*h/4;

    unsigned char r,g,b;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            int start = (i*w + j)*3;
            // 注意r分量存储在低字节,b分量存储在高字节
            r = rgbbuf[start]; 
            g = rgbbuf[start+1]; 
            b = rgbbuf[start+2];

            int y = ((66*r + 129*g + 25*b + 128)>>8) + 16;
            *pY++ = clip_0_255(y);

            //采样2个y时取1个u或v
            if (i % 2 == 0 && j % 2 == 0) { // uv的采样在水平和垂直方向都是p的一半
                int u = ((-38*r - 74*g + 112*b + 128)>>8) + 128;
                *pU++ =  clip_0_255(u);
            }
            else if (i % 2 == 0 && j % 2 == 1) {
                int v = ((112*r - 94*g - 18*b + 128)>>8) + 128;
                *pV++ =  clip_0_255(v);
            }
        }
    }
}

void rgb24_to_yuv420(const char *rgbfile, int w, int h, const char *yuvfile) {
    FILE *frgb = fopen(rgbfile, "r");
    FILE *fyuv = fopen(yuvfile, "w+");

    int rgbsize = w*h*3, yuvsize = w*h*3/2;
    unsigned char rgbbuf[rgbsize];
    unsigned char yuvbuf[yuvsize];
    fread(rgbbuf, 1, rgbsize, frgb);
    
    data_conversion(rgbbuf, w, h, yuvbuf);
    fwrite(yuvbuf, 1, yuvsize, fyuv);

    fclose(frgb);
    fclose(fyuv);
}

函数调用:rgb24_to_yuv420("rgbtest.rgb", 352, 288, "rgbtoyuv.yuv");


2、yuv --> rgb

R = (298Y + 411 V - 57344)>>8
G = (298Y - 101 U - 211 V+ 34739)>>8
B = (298Y + 519 U- 71117)>>8

代码:

void data_conversion(unsigned char *yuvbuf, int w, int h, unsigned char *rgbbuf) {
    unsigned char *pY = yuvbuf;
    unsigned char *pU = yuvbuf + w*h;
    unsigned char *pV = pU + w*h/4;

    int cnt = 0;
    int yIdx, uIdx, vIdx;
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            yIdx = i*w + j;
            uIdx = vIdx = (i/4)*w + j/2;

            int R = (298*pY[yIdx] + 411*pV[vIdx] - 57344)>>8;
            int G = (298*pY[yIdx] - 101*pU[uIdx] - 211*pV[vIdx] + 34739)>>8;
            int B = (298*pY[yIdx] + 519*pU[uIdx] - 71117)>>8;
            
            rgbbuf[cnt++] = clip_0_255(R);
            rgbbuf[cnt++] = clip_0_255(G);
            rgbbuf[cnt++] = clip_0_255(B);
        }
    }
}

你可能感兴趣的:(音视频开发,rgb,yuv)