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

📄 camsnap.c

📁 程序是根据vidcat改的,只能抓PPM的图. makefile的内容如下,请注意打小写: cc=gcc #cflags=-i/firendly-arm/kernel/include -i/
💻 C
字号:
/*
 * camsnap.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/time.h> /* gettimeofday() */
#include <fcntl.h>
#include <unistd.h>
#include <linux/types.h>
#include <linux/videodev.h>

#define def_width 320 /* default width */
#define def_height 240 /* default height */

#define fmt_unknown  0
#define fmt_ppm   1
#define fmt_pgm   2
#define fmt_png   3
#define fmt_jpeg  4
#define fmt_yuv4mpeg 5

#define in_tv   0
#define in_composite 1
#define in_composite2 2
#define in_svideo  3

#define norm_pal  0
#define norm_ntsc  1
#define norm_secam  2

#define input_default -1
#define norm_default -1

#ifndef true
#define true 1
#endif
#ifndef false
#define false 0
#endif

#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))

char *basename (const char *s);

/* globals
 */
static int verbose = 0;

/*
 */
void
usage (char *pname)
{
 fprintf (stderr,
 "vidcat, version %s\n"
 "usage: %s <options>\n"
 " -d <device>                 video device (default: "video_dev")\n"
 " -o <file>                   write output to file instead of stdout\n"
 " -s nxn                      define size of the output image (default:"
  " %dx%d)\n"
 "example: vidcat | xsetbg stdin\n",
  version, (char*)basename(pname), def_width, def_height);
 exit (1);
}
/*
 * set the input and norm for the video4linux device
 */
int
v4l_set_input (int fd, int input, int norm)
{
 struct video_channel vid_chnl;

 if (input != input_default || norm != norm_default) {
  if (vid_chnl.channel != input_default)
   vid_chnl.channel = input;
  else
   vid_chnl.channel = 0;
  vid_chnl.norm = -1;
  if (ioctl (fd, vidiocgchan, &vid_chnl) == -1) {
   perror ("ioctl (vidiocgchan)");
   return -1;
  } else {
   if (input != 0)
    vid_chnl.channel = input;
   if (norm != norm_default)
    vid_chnl.norm    = norm;
   if (ioctl (fd, vidiocschan, &vid_chnl) == -1) {
    perror ("ioctl (vidiocschan)");
    return -1;
   }
  }
 }
 return 0;
}

/*
 * check the size and readjust if necessary
 */
int
v4l_check_size (int fd, int *width, int *height)
{
 struct video_capability vid_caps;

 if (ioctl (fd, vidiocgcap, &vid_caps) == -1) {
  perror ("ioctl (vidiocgcap)");
  return -1;
 }
 /* readjust if necessary */
 if (*width > vid_caps.maxwidth || *width < vid_caps.minwidth) {
  *width = min (*width, vid_caps.maxwidth);
  *width = max (*width, vid_caps.minwidth);
  fprintf (stderr, "readjusting width to %d\n", *width);
 }
 if (*height > vid_caps.maxheight || *height < vid_caps.minheight) {
  *height = min (*height, vid_caps.maxheight);
  *height = max (*height, vid_caps.minheight);
  fprintf (stderr, "readjusting height to %d\n", *height);
 }
 return 0;
}

/*
 * read rgb image from v4l device
 * return: mmap'ed buffer and size
 */
char *
get_image (int dev, int width, int height, int palette ,int *size)
{
 struct video_mbuf vid_buf;
 struct video_mmap vid_mmap;
 char *map;
 int len;
 int bytes = 3;

 if (ioctl (dev, vidiocgmbuf, &vid_buf) == -1) {
  /* to do a normal read()
   */
  struct video_window vid_win;
  if (verbose) {
   fprintf (stderr, "using read()\n");
  }

  if (ioctl (dev, vidiocgwin, &vid_win) != -1) {
   vid_win.width  = width;
   vid_win.height = height;
   if (ioctl (dev, vidiocswin, &vid_win) == -1) {
    perror ("ioctl(vidiocswin)");
    return (null);
   }
  }

  map = malloc (width * height * bytes);
  len = read (dev, map, width * height * bytes);
  if (len <=  0) {
   free (map);
   return (null);
  }
  *size = 0;
  return (map);
 }

 map = mmap (0, vid_buf.size, prot_read|prot_write,map_shared,dev,0);
 if ((unsigned char *)-1 == (unsigned char *)map) {
  perror ("mmap()");
  return (null);
 }

 vid_mmap.format = palette;
 vid_mmap.frame = 0;
 vid_mmap.width = width;
 vid_mmap.height = height;
 if (ioctl (dev, vidiocmcapture, &vid_mmap) == -1) {
  perror ("vidiocmcapture");
  fprintf (stderr, "args: width=%d height=%d palette=%d\n",
     vid_mmap.width, vid_mmap.height, vid_mmap.format);
  munmap (map, vid_buf.size);
  return (null);
 }
 if (ioctl (dev, vidiocsync, &vid_mmap.frame) == -1) {
  perror ("vidiocsync");
  munmap (map, vid_buf.size);
  return (null);
 }
 *size = vid_buf.size;
 if (verbose)
  fprintf (stderr, "got picture\n");  
 return (map);
}

/*
 * write ppm image to stdout / file
 */
void
put_image_ppm (file *out, char *image, int width, int height, int binary)
{
 int x, y, ls=0;
 unsigned char *p = (unsigned char *)image;
 if (!binary) {
  fprintf (out, "p3\n%d %d\n%d\n", width, height, 255);
  for (x = 0; x < width; x++) {
   for (y = 0; y < height; y++) {
    fprintf (out, "%03d %03d %03d  ", p[2], p[1], p[0]);
    p += 3;
    if (ls++ > 4) {
     fprintf (out, "\n");
     ls = 0;
    }
   }
  }
  fprintf (out, "\n");
 } else {
  unsigned char buff[3];
  fprintf (out, "p6\n%d %d\n%d\n", width, height, 255);
  for (x = 0; x < width * height; x++) {
   buff[0] = p[2];
   buff[1] = p[1];
   buff[2] = p[0];
   fwrite (buff, 1, 3, out);
   p += 3;
  }
 }
 fflush (out);
}
/*
 * main()
 */
int
main (int argc, char *argv[])
{
 int width = def_width, height = def_height, size, dev = -1, c;
 char *image, *device = video_dev, *file = null;
 int max_try = 5; /* we try 5 seconds/times to open the device */
// int quality = qual_default; /* default jpeg quality setting */
 int input = input_default; /* this means take over current device settings*/
 int norm  = norm_default;
 int palette = video_palette_rgb24;
 file *out = stdout;
 int format = fmt_ppm;

 while ((c = getopt (argc, argv, "d:o:s:vv")) != eof) {
  switch (c) {
   case 'd': /* change default device */
    device = optarg;
    break;
   case 'o':
    file = optarg;
    break;
   case 's':
    sscanf (optarg, "%dx%d", &width, &height);
    break;
   case 'v':
    verbose++;
    break;
   case 'v':
    printf ("vidcat, version %s\n", version);
    exit (0);
    break;
   default:
    usage (argv[0]);
    break;
  }
 }
 if (verbose) {
  fprintf (stderr, "input palette: %s\n", "rgb" );
  fprintf (stderr, "size: %dx%d\n", width, height);
 }
 if (file) {
  out = fopen (file, "wb");
  if (!out) {
   perror (file);
   return 1;
  }
 }
 /* open the video4linux device */
 while (max_try) {
  dev = open (device, o_rdwr);
  if (dev == -1) {
   if (!--max_try) {
    fprintf (stderr, "can't open device %s\n", device);
    return (1);
   }
   sleep (1);
  } else { break; }
 }
 if (v4l_set_input (dev, input, norm) == -1) {
  return (1);
 }
 if (v4l_check_size (dev, &width, &height) == -1) {
  return (1);
 }
 image = get_image (dev, width, height, palette, &size);
 if (!size)
  close (dev);
 if (image) {
  switch (format) {
   case fmt_ppm:
    put_image_ppm (out, image, width, height, 0);
    break;
   default:
    fprintf (stderr, "unknown format (%d)\n", format);
    break;
  }
  if (size) {
   munmap (image, size);
   close (dev);
  } else if (image) {
   free (image);
  }
 } else {
  fprintf (stderr, "error: can't get image\n");
 }
 return (0);
}

⌨️ 快捷键说明

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