1. 程式人生 > >yuv422轉RGB888儲存bmp檔案解析

yuv422轉RGB888儲存bmp檔案解析

uvc相機支援v4l2程式設計,採集格式若只支援yuv422,使用libjpeg等壓縮速度降低,直接儲存bmp點陣圖速度加快.

關於v4l2對於相機的初始化部分進行省略.

分為幾個關鍵步驟進行轉換:

1:初始化正常

2:將底層獲取與申請的記憶體存入快取進行mmap進行記憶體對映,核心空間的地址不能直接被使用者空間使用

  struct buffer{         void *start;         unsigned int length;     }*buffers;

       //mmap for buffers        buffers = (struct buffer*)malloc(req.count*sizeof (*buffers));

       buffers[n_buffers].length = buf.length;        //map         buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED, fd, buf.m.offset);inx

進行記憶體對映後,可以開始採集,取出快取中的取樣快取,該buffers結構體中儲存的為yuyv資料

3:對yuyv資料進行rgb888轉換

基本思路:

    yuv422採集類似隔點取樣儲存格式編碼.若採集為800*600影象資料

實際在原始的資料中width的資料為800*2.height不變為600.

進行轉換時候.for(i=0;i<IMAGEHEIGHT;i++)

for(j=0;j<IMAGEWIDTH/2;j++)

    y1 = *( pointer + (i*IMAGEWIDTH/2+j)*4+0);        // u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);         y2 = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 2);        //v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);         v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);         u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);

}

}

解析對於yuv422取樣,思路是將列中,每次取4個位元組,以4個位元組為單位

所以for(j=0;j<(width*2)/4;j++)  若取指定的位置的資料

i*(width*2)跳過該行之前的資料,j*4某一列的單位的資料

*pointer指向資料的起始地址,一個單位的資料4個位元組分別存放yuyv;

所以y1=*(pointer+i*(width*2)+j*4 + 0)又由於bmp中儲存g b分量是顛倒的

v = *(pointer+i*(width*2)+j*4 + 1) ,y2=*(pointer+i*(width*2)+j*4 + 2)

u = *(pointer+i*(width*2)+j*4 + 3);

再此基礎上再進行bgr的轉換,下面的公式進行了白平衡處理

 b1 = (1.164*(y1-16)+1.159*(v-128));         g1 = (1.164*(y1-16)-0.392*(u-128)-0.813*(v-128));         r1 = (1.164*(y1-16)+2.018*(u-128));

        b2 = (1.164*(y2-16)+1.159*(v-128));         g2 = (1.164*(y2-16)-0.392*(u-128)-0.813*(v-128));         r2 = (1.164*(y2-16)+2.018*(u-128));

由於rgb格式為3個位元組一個畫素,使用rgb轉換bmp時候.

unsigned char frame_buffer[width*height*3];

 *(frame_buffer + (i*IMAGEWIDTH/2+j)*6    ) = (unsigned char)b1;         *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 1) = (unsigned char)g1;         *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 2) = (unsigned char)r1;

        *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 3) = (unsigned char)b2;         *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 4) = (unsigned char)g2;         *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 5) = (unsigned char)r2;

原理同上