yuv420(planer) to bgr24 to bmp

项目中碰到了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/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值