YUYV攝像頭採集jpeg格式圖片

  1. #include <unistd.h>  
  2. #include <sys/types.h>  
  3. #include <sys/stat.h>  
  4. #include <fcntl.h>  
  5. #include <stdio.h>  
  6. #include <sys/ioctl.h>  
  7. #include <stdlib.h>  
  8. #include <sys/mman.h>  
  9. #include <linux/types.h>  
  10. #include <linux/videodev2.h>  
  11. #include <setjmp.h>  
  12. #include "jpeglib.h"  
  13.    
  14. //#include "v4l2grab.h"  
  15.   
  16. typedef int BOOL;  
  17.   
  18. #define  TRUE    1  
  19. #define  FALSE    0  
  20.   
  21. #define FILE_VIDEO     "/dev/video0"  
  22. //#define BMP          "image_bmp.bmp"  
  23. #define YUV        "image_yuv.yuv"  
  24. #define JPEG        "image_jpeg.jpg"  
  25.   
  26. #define  IMAGEWIDTH    320  
  27. #define  IMAGEHEIGHT   240  
  28.   
  29. static   int      fd;  
  30. static   struct   v4l2_capability   cap;  
  31. struct v4l2_fmtdesc fmtdesc;  
  32. struct v4l2_format fmt,fmtack;  
  33. struct v4l2_streamparm setfps;    
  34. struct v4l2_requestbuffers req;  
  35. struct v4l2_buffer buf;  
  36. enum v4l2_buf_type type;  
  37. unsigned char frame_buffer[IMAGEWIDTH*IMAGEHEIGHT*3];  
  38.   
  39.   
  40. struct buffer  
  41. {  
  42.     void * start;  
  43.     unsigned int length;  
  44. } * buffers;  
  45.    
  46. int init_v4l2(void)  
  47. {  
  48.     int i;  
  49.     int ret = 0;  
  50.       
  51.     //opendev  
  52.     if ((fd = open(FILE_VIDEO, O_RDWR)) == -1)   
  53.     {  
  54.         printf("Error opening V4L interface\n");  
  55.         return (FALSE);  
  56.     }  
  57.   
  58.     //query cap  
  59.     if (ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1)   
  60.     {  
  61.         printf("Error opening device %s: unable to query device.\n",FILE_VIDEO);  
  62.         return (FALSE);  
  63.     }  
  64.     else  
  65.     {  
  66.          printf("driver:\t\t%s\n",cap.driver);  
  67.          printf("card:\t\t%s\n",cap.card);  
  68.          printf("bus_info:\t%s\n",cap.bus_info);  
  69.          printf("version:\t%d\n",cap.version);  
  70.          printf("capabilities:\t%x\n",cap.capabilities);  
  71.            
  72.          if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == V4L2_CAP_VIDEO_CAPTURE)   
  73.          {  
  74.             printf("Device %s: supports capture.\n",FILE_VIDEO);  
  75.         }  
  76.   
  77.         if ((cap.capabilities & V4L2_CAP_STREAMING) == V4L2_CAP_STREAMING)   
  78.         {  
  79.             printf("Device %s: supports streaming.\n",FILE_VIDEO);  
  80.         }  
  81.     }   
  82.       
  83.     //emu all support fmt  
  84.     fmtdesc.index=0;  
  85.     fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  86.     printf("Support format:\n");  
  87.     while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1)  
  88.     {  
  89.         printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);  
  90.         fmtdesc.index++;  
  91.     }  
  92.       
  93.     //set fmt  
  94.         fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  95.     fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;  
  96.     fmt.fmt.pix.height = IMAGEHEIGHT;  
  97.     fmt.fmt.pix.width = IMAGEWIDTH;  
  98.     fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;  
  99.       
  100.     if(ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)  
  101.     {  
  102.         printf("Unable to set format\n");  
  103.         return FALSE;  
  104.     }       
  105.     if(ioctl(fd, VIDIOC_G_FMT, &fmt) == -1)  
  106.     {  
  107.         printf("Unable to get format\n");  
  108.         return FALSE;  
  109.     }   
  110.     {  
  111.          printf("fmt.type:\t\t%d\n",fmt.type);  
  112.          printf("pix.pixelformat:\t%c%c%c%c\n",fmt.fmt.pix.pixelformat & 0xFF, (fmt.fmt.pix.pixelformat >> 8) & 0xFF,(fmt.fmt.pix.pixelformat >> 16) & 0xFF, (fmt.fmt.pix.pixelformat >> 24) & 0xFF);  
  113.          printf("pix.height:\t\t%d\n",fmt.fmt.pix.height);  
  114.          printf("pix.width:\t\t%d\n",fmt.fmt.pix.width);  
  115.          printf("pix.field:\t\t%d\n",fmt.fmt.pix.field);  
  116.     }  
  117.     //set fps  
  118.     setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  119.     setfps.parm.capture.timeperframe.numerator = 10;  
  120.     setfps.parm.capture.timeperframe.denominator = 10;  
  121.       
  122.     printf("init %s \t[OK]\n",FILE_VIDEO);  
  123.           
  124.     return TRUE;  
  125. }  
  126.   
  127. int v4l2_grab(void)  
  128. {  
  129.     unsigned int n_buffers;  
  130.       
  131.     //request for 4 buffers   
  132.     req.count=4;  
  133.     req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  134.     req.memory=V4L2_MEMORY_MMAP;  
  135.     if(ioctl(fd,VIDIOC_REQBUFS,&req)==-1)  
  136.     {  
  137.         printf("request for buffers error\n");  
  138.     }  
  139.   
  140.     //mmap for buffers  
  141.     buffers = malloc(req.count*sizeof (*buffers));  
  142.     if (!buffers)   
  143.     {  
  144.         printf ("Out of memory\n");  
  145.         return(FALSE);  
  146.     }  
  147.       
  148.     for (n_buffers = 0; n_buffers < req.count; n_buffers++)   
  149.     {  
  150.         buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  151.         buf.memory = V4L2_MEMORY_MMAP;  
  152.         buf.index = n_buffers;  
  153.         //query buffers  
  154.         if (ioctl (fd, VIDIOC_QUERYBUF, &buf) == -1)  
  155.         {  
  156.             printf("query buffer error\n");  
  157.             return(FALSE);  
  158.         }  
  159.   
  160.         buffers[n_buffers].length = buf.length;  
  161.         //map  
  162.         buffers[n_buffers].start = mmap(NULL,buf.length,PROT_READ |PROT_WRITE, MAP_SHARED, fd, buf.m.offset);  
  163.         if (buffers[n_buffers].start == MAP_FAILED)  
  164.         {  
  165.             printf("buffer map error\n");  
  166.             return(FALSE);  
  167.         }  
  168.     }  
  169.           
  170.     //queue  
  171.     for (n_buffers = 0; n_buffers < req.count; n_buffers++)  
  172.     {  
  173.         buf.index = n_buffers;  
  174.         ioctl(fd, VIDIOC_QBUF, &buf);  
  175.     }   
  176.       
  177.     type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  
  178.     ioctl (fd, VIDIOC_STREAMON, &type);  
  179.       
  180.     ioctl(fd, VIDIOC_DQBUF, &buf);  
  181.   
  182.     printf("grab yuyv OK\n");  
  183.     return(TRUE);  
  184. }  
  185.   
  186.   
  187. int yuyv_2_rgb888(void)  
  188. {  
  189.     int           i,j;  
  190.     unsigned char y1,y2,u,v;  
  191.     int r1,g1,b1,r2,g2,b2;  
  192.     char * pointer;  
  193.   
  194.     pointer = buffers[0].start;  
  195.   
  196.     for(i=0;i<IMAGEHEIGHT;i++)  
  197.     {  
  198.     for(j=0;j<IMAGEWIDTH/2;j++)//每次取4個字節,也就是兩個像素點,轉換rgb,6個字節,還是兩個像素點  
  199.     {  
  200.     y1 = *( pointer + (i*IMAGEWIDTH/2+j)*4);       
  201.     u  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 1);  
  202.     y2 = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 2);  
  203.     v  = *( pointer + (i*IMAGEWIDTH/2+j)*4 + 3);  
  204.   
  205.     r1 = y1 + 1.042*(v-128);  
  206.     g1 = y1 - 0.34414*(u-128) - 0.71414*(v-128);  
  207.     b1 = y1 + 1.772*(u-128);  
  208.   
  209.     r2 = y2 + 1.042*(v-128);  
  210.     g2 = y2 - 0.34414*(u-128) - 0.71414*(v-128);  
  211.     b2 = y2 + 1.772*(u-128);  
  212.   
  213.     if(r1>255)  
  214.     r1 = 255;  
  215.     else if(r1<0)  
  216.     r1 = 0;  
  217.   
  218.     if(b1>255)  
  219.     b1 = 255;  
  220.     else if(b1<0)  
  221.     b1 = 0;      
  222.   
  223.     if(g1>255)  
  224.     g1 = 255;  
  225.     else if(g1<0)  
  226.     g1 = 0;      
  227.   
  228.     if(r2>255)  
  229.     r2 = 255;  
  230.     else if(r2<0)  
  231.     r2 = 0;  
  232.   
  233.     if(b2>255)  
  234.     b2 = 255;  
  235.     else if(b2<0)  
  236.     b2 = 0;      
  237.   
  238.     if(g2>255)  
  239.     g2 = 255;  
  240.     else if(g2<0)  
  241.     g2 = 0;          
  242.   
  243.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6    ) = (unsigned char)b1;  
  244.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 1) = (unsigned char)g1;  
  245.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 2) = (unsigned char)r1;  
  246.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 3) = (unsigned char)b2;  
  247.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 4) = (unsigned char)g2;  
  248.     *(frame_buffer + (i*IMAGEWIDTH/2+j)*6 + 5) = (unsigned char)r2;  
  249.     }  
  250.     }  
  251.     printf("change to RGB OK \n");  
  252. }  
  253.   
  254. BOOL encode_jpeg(char *lpbuf,int width,int height)  
  255. {  
  256.     struct jpeg_compress_struct cinfo ;  
  257.     struct jpeg_error_mgr jerr ;  
  258.     JSAMPROW  row_pointer[1] ;  
  259.     int row_stride ;  
  260.     char *buf=NULL ;  
  261.     int x ;  
  262.   
  263.     FILE *fptr_jpg = fopen (JPEG,"wb");//注意這裏爲什麼用fopen而不用open  
  264.     if(fptr_jpg==NULL)  
  265.     {  
  266.     printf("Encoder:open file failed!/n") ;  
  267.      return FALSE;  
  268.     }  
  269.   
  270.     cinfo.err = jpeg_std_error(&jerr);  
  271.     jpeg_create_compress(&cinfo);  
  272.     jpeg_stdio_dest(&cinfo, fptr_jpg);  
  273.   
  274.     cinfo.image_width = width;  
  275.     cinfo.image_height = height;  
  276.     cinfo.input_components = 3;  
  277.     cinfo.in_color_space = JCS_RGB;  
  278.   
  279.     jpeg_set_defaults(&cinfo);  
  280.   
  281.   
  282.     jpeg_set_quality(&cinfo, 80,TRUE);  
  283.   
  284.   
  285.     jpeg_start_compress(&cinfo, TRUE);  
  286.   
  287.     row_stride = width * 3;  
  288.     buf=malloc(row_stride) ;  
  289.     row_pointer[0] = buf;  
  290.     while (cinfo.next_scanline < height)  
  291.     {  
  292.      for (x = 0; x < row_stride; x+=3)  
  293.     {  
  294.   
  295.     buf[x]   = lpbuf[x];  
  296.     buf[x+1] = lpbuf[x+1];  
  297.     buf[x+2] = lpbuf[x+2];  
  298.   
  299.     }  
  300.     jpeg_write_scanlines (&cinfo, row_pointer, 1);//critical  
  301.     lpbuf += row_stride;  
  302.     }  
  303.   
  304.     jpeg_finish_compress(&cinfo);  
  305.     fclose(fptr_jpg);  
  306.     jpeg_destroy_compress(&cinfo);  
  307.     free(buf) ;  
  308.     return TRUE ;  
  309.   
  310. }    
  311.   
  312. int close_v4l2(void)  
  313. {  
  314.      if(fd != -1)   
  315.      {  
  316.          close(fd);  
  317.          return (TRUE);  
  318.      }  
  319.      return (FALSE);  
  320. }  
  321.   
  322.   
  323. int main(void)  
  324. {  
  325.     FILE * fp2;  
  326.   
  327.     if(init_v4l2() == FALSE)   
  328.     {  
  329.     return(FALSE);  
  330.     }  
  331.     v4l2_grab();  
  332.   
  333.     yuyv_2_rgb888();                  //yuyv to RGB24  
  334.   
  335.     encode_jpeg(frame_buffer,IMAGEWIDTH,IMAGEHEIGHT); //RGB24 to Jpeg  
  336.     printf("save "JPEG"OK\n");  
  337.   
  338.     close_v4l2();  
  339.   
  340.     return(TRUE);  
  341. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章