1. 程式人生 > >yuv轉RGB

yuv轉RGB

先區分一下YUV和YCbCr

YUV色彩模型來源於RGB模型,

該模型的特點是將亮度和色度分離開,從而適合於影象處理領域。

應用:模擬領域

Y'= 0.299*R' + 0.587*G' + 0.114*B'

U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')

V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')

R' = Y' + 1.140*V'

G' = Y' - 0.394*U' - 0.581*V'

B' = Y' + 2.032*U'

YCbCr模型來源於YUV模型。YCbCr是 YUV 顏色空間的偏移版本.

應用:數字視訊,ITU-R BT.601建議

Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16

Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128

Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128

static int yuv_tbl_ready=0;
static int y1192_tbl[256];
static int v1634_tbl[256];
static int v833_tbl[256];
static int u400_tbl[256];
static int u2066_tbl[256];
int yuyv422_to_abgr(char *dst,char *src,int height,int width)
{
    int i;
    int frame_size = width*height*2;

    if(!dst){
        return -1;
    }
    int *lrgb = (int *)dst;

    if(yuv_tbl_ready==0){
        for(i=0 ; i<256 ; i++){
            y1192_tbl[i] = 1192*(i-16);
            if(y1192_tbl[i]<0){
                y1192_tbl[i]=0;
            }

            v1634_tbl[i] = 1634*(i-128);
            v833_tbl[i] = 833*(i-128);
            u400_tbl[i] = 400*(i-128);
            u2066_tbl[i] = 2066*(i-128);
        }
        yuv_tbl_ready=1;
    }

    for(i=0 ; i<frame_size ; i+=4){
        unsigned char y1, y2, u, v;
        y1 = src[i];
        u = src[i+1];
        y2 = src[i+2];
        v = src[i+3];

        int y1192_1=y1192_tbl[y1];
        int r1 = (y1192_1 + v1634_tbl[v])>>10;
        int g1 = (y1192_1 - v833_tbl[v] - u400_tbl[u])>>10;
        int b1 = (y1192_1 + u2066_tbl[u])>>10;

        int y1192_2=y1192_tbl[y2];
        int r2 = (y1192_2 + v1634_tbl[v])>>10;
        int g2 = (y1192_2 - v833_tbl[v] - u400_tbl[u])>>10;
        int b2 = (y1192_2 + u2066_tbl[u])>>10;

        r1 = r1>255 ? 255 : r1<0 ? 0 : r1;
        g1 = g1>255 ? 255 : g1<0 ? 0 : g1;
        b1 = b1>255 ? 255 : b1<0 ? 0 : b1;
        r2 = r2>255 ? 255 : r2<0 ? 0 : r2;
        g2 = g2>255 ? 255 : g2<0 ? 0 : g2;
        b2 = b2>255 ? 255 : b2<0 ? 0 : b2;

        *lrgb++ = 0xff000000 | b1<<16 | g1<<8 | r1;
        *lrgb++ = 0xff000000 | b2<<16 | g2<<8 | r2;

    }
    return 0;
}

R' = 1.164*(Y’-16) + 1.596*(Cr'-128)

G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)

B' = 1.164*(Y’-16) + 2.017*(Cb'-128)

PS: 上面各個符號都帶了一撇,表示該符號在原值基礎上進行了伽馬校正,伽馬校正有助於彌補在抗鋸齒的過程中,線性分配伽馬值所帶來的細節損失,使影象細節更加豐富。在沒有采用伽馬校正的情況下,暗部細節不容易顯現出來,而採用了這一影象增強技術以後,影象的層次更加明晰了。

所以說H264裡面的YUV應屬於YCbCr, 也可以點這裡獲得其他一些資訊.

下面在仔細談談YUV格式, YUV格式通常有兩大類:打包(packed)格式和平面(planar)格式。前者將YUV分量存放在同一個陣列中,通常是幾個相鄰的畫素組成一個巨集畫素(macro-pixel);而後者使用三個陣列分開存放YUV三個分量,就像是一個三維平面一樣。

我們常說得YUV420屬於planar格式的YUV, 顏色比例如下:

Y0U0V0             Y1                 Y2U2V2                          Y3

Y4                      Y5                 Y6                                   Y7

Y8U8V8             Y9                 Y10U10V10                   Y11

Y12           Y13          Y14                   Y15

其他格式YUV可以點這裡檢視詳細內容, 而在YUV檔案中YUV420又是怎麼儲存的呢? 在常見H264測試的YUV序列中,例如CIF影象大小的YUV序列(352*288),在檔案開始並沒有檔案頭,直接就是YUV資料,先存第一幀的Y資訊,長度為352*288個byte,然後是第一幀U資訊長度是352*288/4個byte, 最後是第一幀的V資訊,長度是352*288/4個byte, 因此可以算出第一幀資料總長度是352*288*1.5,即152064個byte, 如果這個序列是300幀的話, 那麼序列總長度即為152064*300=44550KB,這也就是為什麼常見的300幀CIF序列總是44M的原因.