Example 2.13. V4L2_PIX_FMT_YUYV 4 × 4 pixelimage
start + 0: |
Y'00 |
Cb00 |
Y'01 |
Cr00 |
Y'02 |
Cb01 |
Y'03 |
Cr01 |
start + 8: |
Y'10 |
Cb10 |
Y'11 |
Cr10 |
Y'12 |
Cb11 |
Y'13 |
Cr11 |
start + 16: |
Y'20 |
Cb20 |
Y'21 |
Cr20 |
Y'22 |
Cb21 |
Y'23 |
Cr21 |
start + 24: |
Y'30 |
Cb30 |
Y'31 |
Cr30 |
Y'32 |
Cb31 |
Y'33 |
Cr31 |
YUV422碼流存放位置
(轉自http://www.chineselinuxuniversity.net/kerneldocs/media/V4L2-PIX-FMT-YUYV.html)
Example 2.18. V4L2_PIX_FMT_YUV420 4 × 4 pixelimage
start + 0: |
Y'00 |
Y'01 |
Y'02 |
Y'03 |
start + 4: |
Y'10 |
Y'11 |
Y'12 |
Y'13 |
start + 8: |
Y'20 |
Y'21 |
Y'22 |
Y'23 |
start + 12: |
Y'30 |
Y'31 |
Y'32 |
Y'33 |
start + 16: |
Cb00 |
Cb01 |
|
|
start + 18: |
Cb10 |
Cb11 |
|
|
start + 20: |
Cr00 |
Cr01 |
|
|
start + 22: |
Cr10 |
Cr11 |
|
|
|
|
|
|
|
YUV420碼流存放位置
(轉自http://www.chineselinuxuniversity.net/kerneldocs/media/re18.html該處是YVU420)
這里要順帶提一下YUV444,既無損YUV色彩空間.一個Y帶一個Cb一個Cr,即YCbCr.
YUV422采樣即從YUV444基礎上,從第一個Y開始只保留Cb,剔去Cr,第二個Y只保留Cr剔去Cb…...這樣交替采樣,長度大小為width*height*2,Y:U:V=4:2:2,一個色彩分量占一個字節.
而YUV420即從YUV422基礎上進行隔行采樣,例如第一行只保留Cb,第二行只保留Cr……這樣交替進行,Y:U:V=4:2:0並不是沒有V分量,也可以是Y:U:V=4:0:2.相信這樣大家容易理解.最后在這個基礎上,把Y,U,V三種分量打包排列,即如上圖,長度大小為width*height*3/2.
說了這么多,是時候貼上具體代碼.
- <span style="font-size:14px;">#include <stdio.h>
- #include <string.h>
- #define READ_WRITE_FILE_SIZE 176*144*2 //YUV422 圖像分辨率為177x144
- unsigned char filebuf[38017] = {0};
- int YUV422To420(unsigned char yuv422[], unsigned char yuv420[], int width, int height)
- {
- int ynum=width*height;
- int i,j,k=0;
- //得到Y分量
- for(i=0;i<ynum;i++){
- yuv420[i]=yuv422[i*2];
- }
- //得到U分量
- for(i=0;i<height;i++){
- if((i%2)!=0)continue;
- for(j=0;j<(width/2);j++){
- if((4*j+1)>(2*width))break;
- yuv420[ynum+k*2*width/4+j]=yuv422[i*2*width+4*j+1];
- }
- k++;
- }
- k=0;
- //得到V分量
- for(i=0;i<height;i++){
- if((i%2)==0)continue;
- for(j=0;j<(width/2);j++){
- if((4*j+3)>(2*width))break;
- yuv420[ynum+ynum/4+k*2*width/4+j]=yuv422[i*2*width+4*j+3];
- }
- k++;
- }
- return 1;
- }
- int main(void)
- {
- int len = 0;
- FILE *fpr, *fpw;
- unsigned char buf[READ_WRITE_FILE_SIZE];
- fpr = fopen( "WEBCAM-00012.YUV", "rb" );
- fpw = fopen( "yuyv_2_yy_u_v.yuv", "wb" );
- if( fpr == NULL || fpw == NULL )
- {
- printf("can not read or write file\n");
- fcloseall();
- return 1;
- }
- fread( buf, READ_WRITE_FILE_SIZE, 1, fpr );
- if(YUV422To420(buf,filebuf,176,144))printf("ok\n");
- printf("size:%d",sizeof(filebuf));
- fwrite( &filebuf, sizeof(filebuf), 1, fpw );
- fcloseall();
- return 0;
- }
- </span>
- <span style="font-size:14px;">#include <stdio.h>
- #include <string.h>
- #define READ_WRITE_FILE_SIZE 176*144*2 //YUV422 圖像分辨率為177x144
- unsigned char filebuf[38017] = {0};
- int YUV422To420(unsigned char yuv422[], unsigned char yuv420[], int width, int height)
- {
- int ynum=width*height;
- int i,j,k=0;
- //得到Y分量
- for(i=0;i<ynum;i++){
- yuv420[i]=yuv422[i*2];
- }
- //得到U分量
- for(i=0;i<height;i++){
- if((i%2)!=0)continue;
- for(j=0;j<(width/2);j++){
- if((4*j+1)>(2*width))break;
- yuv420[ynum+k*2*width/4+j]=yuv422[i*2*width+4*j+1];
- }
- k++;
- }
- k=0;
- //得到V分量
- for(i=0;i<height;i++){
- if((i%2)==0)continue;
- for(j=0;j<(width/2);j++){
- if((4*j+3)>(2*width))break;
- yuv420[ynum+ynum/4+k*2*width/4+j]=yuv422[i*2*width+4*j+3];
- }
- k++;
- }
- return 1;
- }
- int main(void)
- {
- int len = 0;
- FILE *fpr, *fpw;
- unsigned char buf[READ_WRITE_FILE_SIZE];
- fpr = fopen( "WEBCAM-00012.YUV", "rb" );
- fpw = fopen( "yuyv_2_yy_u_v.yuv", "wb" );
- if( fpr == NULL || fpw == NULL )
- {
- printf("can not read or write file\n");
- fcloseall();
- return 1;
- }
- fread( buf, READ_WRITE_FILE_SIZE, 1, fpr );
- if(YUV422To420(buf,filebuf,176,144))printf("ok\n");
- printf("size:%d",sizeof(filebuf));
- fwrite( &filebuf, sizeof(filebuf), 1, fpw );
- fcloseall();
- return 0;
- }