免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1289 | 回复: 0
打印 上一主题 下一主题

yuv420p转bmp图片(2410平台) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-08-12 19:54 |只看该作者 |倒序浏览
最近做一个视频采集,为了调试,先截了图片出来,涉及到图片的转换。调试过程花了一定的时间,现把源代码奉上,供大家参考
#include stdio.h>
#include stdlib.h>
#include unistd.h>
#include linux/videodev.h>
#include sys/ioctl.h>
#include fcntl.h>
#include linux/fb.h>
#include sys/mman.h>
#include linux/delay.h>
#include time.h>
#define ERR_FRAME_BUFFER    1
#define ERR_VIDEO_OPEN        2
#define ERR_VIDEO_GCAP        3
#define ERR_VIDEO_GPIC        4
#define ERR_VIDEO_SPIC        5
#define ERR_SYNC            6
#define ERR_FRAME_USING 7
#define ERR_GET_FRAME 8
typedef struct    _fb_v4l
{
  int fbfd ;                        
  struct fb_var_screeninfo vinfo;        
  struct fb_fix_screeninfo finfo;   
  char *fbp;                        
                                    
  int fd;                                    
  struct video_capability capability;     
  struct video_buffer      buffer;        
  struct video_window      window;        
  struct video_channel      channel[8];     
  struct video_picture      picture;   
  struct video_tuner      tuner;        
  struct video_audio      audio[8];        
  struct video_mmap      mmap;            
  struct video_mbuf      mbuf;            
  unsigned char      *map;                           
  int frame_current;
  int frame_using[VIDEO_MAX_FRAME];
}fb_v41;
struct file_header
{
  unsigned short bfType; // Picture tpye, must set to 19778
  int bfSize; // The file size in bytes
  int bfRev; // Reserved
  int bfOffBits; // the offset from the beginning of the file to the bitmap data.
}__attribute__ ((packed));
struct info_header
{
  int biSize; // info_header's size in bytes
  int biWidth; // width in pixels
  int biHeight;//height in pixels
  short biPlanes; //the number of planes of the target device
  short biBitCount; //the number of bits per pixel
  int biCompression;//the type of compression
  int biSizeImage; //
  int biXPelsPerMeter;//usually set to zero
  int biYPelsPerMeter;//usually set to zero
  int biClrUsed;//the number of colors used in the bitmap
  int biClrImportant;
}__attribute__ ((packed));
struct bmp_file
{
  struct file_header header;
  struct info_header info;
  unsigned char bits[640*480*3];
}__attribute__ ((packed));
#define V4L_FILE "/dev/video0"
int get_grab_frame(fb_v41 *vd, int frame)
{
  if (vd->frame_using[frame])
    {
      fprintf(stderr, "get_grab_frame: frame %d is already used.\n", frame);
      return ERR_FRAME_USING;
    }
  vd->mmap.frame = frame;
  if (ioctl(vd->fd, VIDIOCMCAPTURE, &(vd->mmap))  0)
    {
      perror("v4l_grab_frame");
      return ERR_GET_FRAME;
    }
  vd->frame_using[frame] = 1;
  vd->frame_current = frame;
  return 0;
}
int get_first_frame(fb_v41 *vd)
{
  int ret;
  
  vd->frame_current = 0;
  ret = get_grab_frame( vd, 0 );
  if ( ret0 )
    return ret;
  if (ioctl(vd->fd, VIDIOCSYNC, &(vd->frame_current))  0)
    {
      perror("v4l_grab_sync");
      return ERR_SYNC;
    }
  vd->frame_using[vd->frame_current] = 0 ;
        
  return (0);
}
int get_next_frame(fb_v41 *vd)
{
  int ret;
  vd->frame_current ^= 1;
  ret = get_grab_frame( vd,vd->frame_current);        
  if( ret  0 )
    return ret;
        
  if (ioctl(vd->fd, VIDIOCSYNC, &(vd->frame_current))  0)
    {
      perror("v4l_grab_sync");
      return ERR_SYNC;
    }
  vd->frame_using[vd->frame_current] = 0 ;
  
  return 0;   
}
unsigned char *get_frame_address(fb_v41 *vd)
{
  return (vd->map + vd->mbuf.offsets[vd->frame_current]);
}
int open_video( char *fileptr,fb_v41 *vd ,int dep,int pal,int width,int height)
{
  if ((vd->fd = open(fileptr, O_RDWR))  0)
    {
      perror("v4l_open:");
      return ERR_VIDEO_OPEN;
    }
  if (ioctl(vd->fd, VIDIOCGCAP, &(vd->capability))  0)
    {
      perror("v4l_get_capability:");
      return ERR_VIDEO_GCAP;
    }
     
  if (ioctl(vd->fd, VIDIOCGPICT, &(vd->picture))  0)
    {
      perror("v4l_get_picture");
      return ERR_VIDEO_GPIC;
    }
  vd->picture.palette = pal;   
  vd->picture.depth = dep;            
  vd->mmap.format = pal;
  if (ioctl(vd->fd, VIDIOCSPICT, &(vd->picture))  0)
    {
      perror("v4l_set_palette");
      return ERR_VIDEO_SPIC;
    }
  
  vd->mmap.width = width;     
  vd->mmap.height = height;
  vd->mmap.format = vd->picture.palette;
  vd->frame_current = 0;
  vd->frame_using[0] = 0;
  vd->frame_using[1] = 0;
   
  if (ioctl(vd->fd, VIDIOCGMBUF, &(vd->mbuf))  0)
    {
      perror("v4l_get_mbuf");
      return -1;
    }
  vd->map = mmap(0, vd->mbuf.size, PROT_READ|PROT_WRITE, MAP_SHARED, vd->fd, 0);
  if ( vd->map  0)
    {
      perror("v4l_mmap_init:mmap");
      return -1;
    }
  printf("The video device was opened successfully.\n");
  return 0;
}
static void cvt_420p_to_rgb(int width, int height, const unsigned char *src, unsigned char *dst)
{
  int r, g, b;
  int rdif, gdif, bdif, y;
  int yy, uu, vv;
  int xoff, yoff;
  int numpix = width*height;
  unsigned char *pout = dst + width*height*3;
  for(yoff=0; yoffheight; yoff++)
    {
      for(xoff=0; xoffwidth; xoff++)
    {
     yy = *(src+yoff*640+xoff);
     uu = *(src+(yoff/2)*320+xoff/2+numpix);
     vv = *(src+(yoff/2)*320+xoff/2+numpix+numpix/4);
     uu -= 128;
     vv -= 128;
     r = yy + vv + ((vv*103)>>8);
     g = yy - ((uu*88)>>8) - ((vv*183)>>8);
     b = yy + uu + ((uu*198)>>8);
     if(r>255) { r = 255; }
     if(g>255) { g = 255; }
     if(b>255) { b = 255; }
     if(r0) { r = 0;}
     if(g0) { g = 0;}
     if(b0) { b = 0;}
     *pout = (unsigned char)b;
     pout--;
     *pout = (unsigned char)r;
     pout--;
     *pout = (unsigned char)g;
     pout--;
    }
    }
}
int main( void )
{
  fb_v41 vd;
  int ret,i;
  int k=0;
  unsigned char *imageptr;
  struct bmp_file myfile;
  int fd;
  printf("sizeof short is %d\n", sizeof(short));
  myfile.header.bfType = 19778;
  myfile.header.bfSize = sizeof(struct bmp_file);
  myfile.header.bfRev = 0;
  myfile.header.bfOffBits = 54;
  myfile.info.biSize = 0x28;
  myfile.info.biWidth = 640;
  myfile.info.biHeight = 480;
  myfile.info.biPlanes = 1;
  myfile.info.biBitCount = 24;
  myfile.info.biCompression = 0;
  myfile.info.biSizeImage = 0;
  myfile.info.biClrUsed = 256*256*256;
  myfile.info.biClrImportant = 0;
  myfile.info.biXPelsPerMeter = 2048;
  myfile.info.biYPelsPerMeter = 2048;
  fd = open("./first.bmp", O_RDWR);
  if(fd  0)
    {
      printf("open file error!\n");
      return 0;
    }
      
   
  ret = open_video( V4L_FILE, &vd, 24, VIDEO_PALETTE_YUV420P, 640, 480);
  if( ret )        
    {
      printf("Open video failed!\n");
      goto err;
    }
        
  printf(vd.capability.name);
  printf(", Type:%d\n",vd.capability.type);
  printf("Maxwidth:%d,Maxheight:%d\n",vd.capability.maxwidth ,vd.capability.maxheight);
  printf("Minwidth:%d,Minheight:%d\n",vd.capability.minwidth,vd.capability.minheight);
  printf("Channels:%d,Audios:%d\n",vd.capability.channels,vd.capability.audios);

  for(i=0;i10;i++)
    {
      imageptr = (unsigned char *)get_frame_address(&vd );     
      if(get_next_frame( &vd ) !=0 )   
    {     
     goto err;
    }
      printf("i = %d\n", i);
    }
  cvt_420p_to_rgb(640, 480, imageptr, myfile.bits);
  write(fd, &myfile, sizeof(struct bmp_file));
        
err:
  if(vd.fbfd)
    close(vd.fbfd);
         
  if(vd.fd)
    close(vd.fd);
  exit(0);
  return 0;
}

采集图片大小为640*480,采用24位色。在使用的时候,现要在当前目录下touch一个first.bmp文件,不然运行程序的时候会提示open file error!
图片最后为bmp格式,可以直接在xp下用常用图片软件打开,效果还可以。
说明一下,本程序是由其他程序修改而来,为了避免麻烦,对其中一些没有用的地方并没有删除,但是这样不会影响使用。
大家有问题可以联系我。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/57747/showart_1129208.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP