yuv420(planer) to bgr24 to bmp

來源:互聯網
上載者:User
項目中碰到了YUV420 planer格式轉BGR24的要求(原文中寫為RGB24,但實際應為BGR),BGR格式可直接應用於opencv,發現網上涉及這方面的內容不少,但能用的代碼非常少,據說最新的opencv 已經可以實現這一功能,下面的代碼在項目中可用,轉換成功;標記一下,防止以後再次用到;

unsigned char clip(int valid){
  return valid<0 ? 0 : valid>255 ? 255 : valid;
}
void yuv2bgr(unsigned char *rgbout,unsigned char *yuvin, int width,int height){
    int x,y;
 int temp=0;

    unsigned long  idx=0;
    unsigned char *ybase,*ubase,*vbase;
    unsigned char Y,U,V;
 //分別得到y、u、v分量的指標;planar format
    ybase=yuvin;
    ubase=ybase+width*height;
    vbase=ubase+(width*height)/4;
 for(y=0;y<Height;y++){
  idx=(Height-y-1)*Width*3;//該值保證所產生的rgb資料逆序存放在rgbbuf中
  //printf("this is %dth x and index is %d!!!!!!\n",x,idx);
        for(x=0;x<Width;x++){
             Y=ybase[y*Width+x];
             U=ubase[(y/2)*(Width/2)+x/2];//注意UV分量的取值方法,y/2的含義
             V=vbase[(y/2)*(Width/2)+x/2];
   
             temp=(int)(Y+1.771*(U - 128));
    rgbout[idx++]=clip(temp);

             temp=(int)(Y-0.7145*(V - 128)-0.3456*(U - 128));
    rgbout[idx++]=clip(temp);

    temp=(int)(Y+ 1.4022*(V - 128));
    rgbout[idx++]=clip(temp);

        }
 }
}

int writebmp(char *filename,unsigned char *rgbbuf,int width,int height){
   BITMAPFILEHEADER bmpHeader;
   BITMAPINFOHEADER bmpInfo;
   int linebyte=width*3;//(width*3+3)/4*4;
   int rgb_size=linebyte*height;
   int count;
   unsigned long k=0;
   FILE *bmpfp;
   memset(&bmpHeader,0,sizeof(BITMAPFILEHEADER));
   memset(&bmpInfo,0,sizeof(BITMAPINFOHEADER));
   bmpHeader.bfType=0x4D42;//"MB"
   bmpHeader.bfSize=rgb_size+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
   bmpHeader.bfReserved1=0;
   bmpHeader.bfReserved2=0;
   bmpHeader.bfOffBits=54;//sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFODEADER);
  
   bmpInfo.biSize=sizeof(BITMAPINFOHEADER);
   bmpInfo.biWidth=width;
   bmpInfo.biHeight=height;
   bmpInfo.biPlanes=1;
   bmpInfo.biBitCount=24;
   bmpInfo.biCompression=BI_RGB;
   bmpInfo.biSizeImage=rgb_size;
   bmpInfo.biXPelsPerMeter=0;
   bmpInfo.biYPelsPerMeter=0;
   bmpInfo.biClrUsed=0;
   bmpInfo.biClrImportant=0;
   bmpfp=fopen(filename,"wb");
   if(bmpfp==NULL){
        printf("Failed to open file %s\n",filename);
        return -1;
   }
  
   count=fwrite(&bmpHeader,sizeof(BITMAPFILEHEADER),1,bmpfp);
   if(count!=1){
        printf("Failed  to write bmpheader to file the count is %d\n",count);
        return -1;                             
   }
   count=fwrite(&bmpInfo,sizeof(BITMAPINFOHEADER),1,bmpfp);
   if(count!=1){
        printf("Failed  to write bmpinfo to file the count is %d %d\n",count,sizeof(BITMAPINFOHEADER));
        fclose(bmpfp);
        return -1;                             
   }
   count=fwrite(rgbbuf,1,rgb_size,bmpfp);
   if(count!=rgb_size){
        printf("Failed to write rgbbuf to file the count is %d\n",count);
        fclose(bmpfp);
        return -1;                             
   }
   fclose(bmpfp);

   return 1;
  
}

int main(){
 int i;
    FILE *file_in;
    int yuvsize=Width*Height*3/2;
 int count;
    unsigned char *yuvbuf;
 unsigned char *rgbbuf;
    char bmpfilename[]="first.bmp";
    file_in=fopen("D:\\work\\yuv2rgb\\foreman_cif.yuv","rb");
    if(file_in==NULL){
         printf("failed to open file\n");
         return;
    }
    yuvbuf=(unsigned char*)malloc(yuvsize);
 rgbbuf=(unsigned char*)malloc(Width*Height*3);
 memset(yuvbuf,0,yuvsize);
 memset(rgbbuf,0,Width*Height*3);
    if(yuvbuf==NULL){
         printf("failed to malloc the yuv buffer\n");
         return;           
    }
 if(rgbbuf==NULL){
         printf("failed to malloc the rgb buffer\n");
         return;           
    }
    fseek(file_in,0, SEEK_CUR);//移動檔案指標的位置
    count=fread(yuvbuf,yuvsize,1,file_in);
 if(count!=1){
  printf("failed to read yuv data!\n");
  return;
 }
 fclose(file_in);
    for(i=0;i<1;i++){
       printf("Frame number is %d\n",i);
       yuv2rgb(rgbbuf,yuvbuf,Width,Height);
    if(writebmp(bmpfilename,rgbbuf,Width,Height)==1)
        printf("Success to generate a bmp file\n");

    }
    free(yuvbuf);
 free(rgbbuf);
}

轉自:http://yumingfu.blog.163.com/blog/static/17507717720126307641853/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.