⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.c

📁 实现摄像头驱动功能 能进行摄影 拍摄 拍照等功能
💻 C
字号:
#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <stdlib.h>#include <linux/types.h>#include <linux/videodev.h>#include "jpeglib.h"#include <setjmp.h>#include "SDL.h"#include <string.h>#include <signal.h>#include <errno.h>#define USB_VIDEO "/dev/video0"SDL_Surface *screen,*img;int cam_fd;int width,height;const int bpp = 24;struct video_mmap cam_mm;struct video_capability cam_cap;struct video_picture cam_pic;struct video_mbuf cam_mbuf;struct video_window win;char *cam_data = NULL;int nframe;void errexit(char *msg){  fputs(msg,stderr);  exit(-1);}void e_sig(int signum){  printf("\nERROR:signal %d\n",signum);  exit(-1);}void setup_sighandler(){  signal(SIGTERM,&e_sig);  signal(SIGINT,&e_sig);  signal(SIGSEGV,&e_sig);  signal(SIGILL,&e_sig);  signal(SIGFPE,&e_sig);}void init_video(int w,int h,int bpp); /* bpp == bits per pixel, 暂时无效*/void init_screen(int w,int h,int bpp); /* like above*/void read_video(char *pixels);void show_img(char *pixels);void window_loop();void exchange_r_b( char * f,long size);void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality);void save_snapshot();void free_dev(){  printf("free device\n");  close(cam_fd);}int main(int argc,char *argv[]){  int i;  width = 320;  height = 240;  printf("cc1\n");  atexit( &free_dev );  printf("cc2\n");  init_video(width,height,bpp);  init_screen(width,height,bpp);  setup_sighandler();    window_loop();  getchar();  munmap(cam_data,cam_mbuf.size);  exit(0);}void config_vid_pic(){  int ret;  if (ioctl(cam_fd, VIDIOCGPICT, &cam_pic) < 0) {    errexit("ERROR:VIDIOCGPICT\n");  }    cam_pic.palette = VIDEO_PALETTE_RGB24;    cam_pic.brightness  = 44464;    cam_pic.hue = 36000;    cam_pic.colour = 0;    cam_pic.contrast = 43312;    cam_pic.whiteness = 13312;    cam_pic.depth = 24;    ret = ioctl( cam_fd, VIDIOCSPICT,&cam_pic );          if( ret<0 ) {      close(cam_fd);      errexit("ERROR: VIDIOCSPICT,Can't set video_picture format\n");    }  }void init_video(int w,int h,int bpp) {  int ret;  printf("open the video\n");  cam_fd = open( USB_VIDEO, O_RDWR );  if( cam_fd<0 )    errexit("Can't open video device\n");	  ret = ioctl( cam_fd,VIDIOCGCAP,&cam_cap );         if( ret<0 ) {    errexit("Can't get device information: VIDIOCGCAP\n");  }  printf("Device name:%s\nWidth:%d ~ %d\nHeight:%d ~ %d\n",cam_cap.name, cam_cap.maxwidth, cam_cap.minwidth, cam_cap.maxheight, cam_cap.minheight);  if( ioctl(cam_fd,VIDIOCGWIN,&win)<0 ) {    errexit("ERROR:VIDIOCGWIN\n");  }  win.x = 0;  win.y = 0;  win.width=width;  win.height=height;  if (ioctl(cam_fd, VIDIOCSWIN, &win) < 0) {    errexit("ERROR:VIDIOCSWIN\n");  }  config_vid_pic();      ret = ioctl(cam_fd,VIDIOCGMBUF,&cam_mbuf);  if( ret<0 ) {    errexit("ERROR:VIDIOCGMBUF,Can't get video_mbuf\n");  }  printf("Frames:%d\n",cam_mbuf.frames);  nframe = cam_mbuf.frames;  cam_data = (char*)mmap(0, cam_mbuf.size, PROT_READ|PROT_WRITE,MAP_SHARED,cam_fd,0);  if( cam_data == MAP_FAILED ) {    errexit("ERROR:mmap\n");  }  printf("Buffer size:%d\nOffset:%d\n",cam_mbuf.size,cam_mbuf.offsets[0]);}void init_screen(int w,int h,int bpp) // like above{	  if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 ) {    fprintf(stderr, "无法初始化SDL: %s\n", SDL_GetError());    exit(1);  }  img = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, bpp, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000);  screen = SDL_SetVideoMode(width, height, bpp, SDL_SWSURFACE);  if ( screen == NULL ) {    fprintf(stderr, "无法设置视频模式:%s\n", SDL_GetError());    exit(1);  }  atexit(SDL_Quit);}void read_video(char *pixels){  int ret;  int frame=0;   cam_mm.height = height;  cam_mm.width = width;  cam_mm.frame = 0;  cam_mm.format=VIDEO_PALETTE_RGB24;    ret = ioctl(cam_fd,VIDIOCMCAPTURE,&cam_mm);  if( ret<0 ) {    errexit("ERROR: VIDIOCMCAPTURE\n");  }  ret = ioctl(cam_fd,VIDIOCSYNC,&frame);  if( ret<0 ) {    errexit("ERROR: VIDIOCSYNC\n");  }}void show_img(char *pixels){  int row_stride = width*3;  char *pbuf = (char*)img->pixels;  int row;  for(row=0; row<height; row++) {    memcpy(pbuf, pixels, row_stride);    pbuf += img->pitch;    pixels += row_stride;  }  SDL_BlitSurface(img, NULL, screen, NULL);  SDL_UpdateRect(screen,0,0,width,height);}void window_loop(){  SDL_Event event;  int keystat = 0;  Uint32 ticks = 0;  SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,1000);  while ( 1 ) {    SDL_PollEvent(&event);    switch (event.type) {    case SDL_QUIT:      exit(0);    case SDL_KEYDOWN:      if( event.key.keysym.sym == SDLK_F8 && keystat == 0 )	save_snapshot();      if( event.key.keysym.sym == SDLK_F9 && keystat == 0 )	config_vid_pic();      keystat = 1;      break;    case SDL_KEYUP:      keystat = 0;      break;    default:      break;    }    if( (SDL_GetTicks()-ticks)<100 )      continue;    read_video(NULL);    show_img( cam_data );    ticks = SDL_GetTicks();  }}void compress_to_jpeg_file( FILE *outfile, char * image_buffer,int w,int h, int quality){  struct jpeg_compress_struct cinfo;  struct jpeg_error_mgr jerr;  JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */  int row_stride;  /* physical row width in image buffer */  int image_width;  int image_height;  cinfo.err = jpeg_std_error(&jerr);  jpeg_create_compress(&cinfo);  jpeg_stdio_dest(&cinfo, outfile);  image_width = w;  image_height = h;  cinfo.image_width = image_width;  /* image width and height, in pixels */  cinfo.image_height = image_height;  cinfo.input_components = 3;  /* # of color components per pixel */  cinfo.in_color_space = JCS_RGB;  /* colorspace of input image */  jpeg_set_defaults(&cinfo);  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);  jpeg_start_compress(&cinfo, TRUE);  row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */  while (cinfo.next_scanline < cinfo.image_height) {    row_pointer[0] = (JSAMPROW)& image_buffer[cinfo.next_scanline * row_stride];    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);  }  jpeg_finish_compress(&cinfo);  jpeg_destroy_compress(&cinfo);  }void exchange_r_b( char * f,long size){  char r,b;  long i;  for( i = 0; i < size ; i++)    {      r = *f;      b = *( f + 2);      *f = b;      *(f + 2) = r;      f = f +3;    }}void save_snapshot(){  char *basepath = "/mnt/usb";  char *basename = "/snapsot";  char *extname = ".jpg";  char filename[100];  int i = 0;  FILE *fo;  for(;;) {    sprintf(filename,"%s%s%d%s",basepath,basename,i,extname);    fo = fopen(filename,"rb");    if( fo==NULL )      break;    else      fclose(fo);    i += 1;  }  printf("snapshot:%s\n",filename);  fo = fopen(filename,"wb");  exchange_r_b( cam_data, width*height );  compress_to_jpeg_file( fo, cam_data, width, height, 90 );  fclose(fo);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -