?? vidcat.c
字號:
/* * vidcat.c * * Copyright (C) 1998 - 2001 Rasca, Berlin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#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>#ifdef HAVE_LIBZ#include <zlib.h>#endif#ifdef HAVE_LIBPNG#include <png.h>#endif#ifdef HAVE_LIBJPEG#include <jpeglib.h>#endif#include "v4l.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 QUAL_DEFAULT 80char *basename (const char *s);/* globals */static int verbose = 0;/* */voidusage (char *pname){ fprintf (stderr, "VidCat, Version %s\n" "Usage: %s <options>\n" " -b make a raw PPM instead of an ASCII one\n" " -d <device> video device (default: "VIDEO_DEV")\n" " -f {ppm|jpeg|png|yuv4mpeg} output format of the image\n" " -g greayscale instead of color\n" " -i {tv|comp1|comp2|s-video} which input channel to use\n" " -l loop on, doesn't make sense in most cases\n" " -n {pal|ntsc|secam} select video norm\n" " -o <file> write output to file instead of stdout\n" " -p c|g|y|Y videopalette to use\n" " -q <quality> only for jpeg: quality setting (1-100," " default: %d)\n" " -s NxN define size of the output image (default:" " %dx%d)\n" "Example: vidcat | xsetbg stdin\n", VERSION, (char*)basename(pname), QUAL_DEFAULT, DEF_WIDTH, DEF_HEIGHT); exit (1);}/* */doublems_time (void){ static struct timeval tod; gettimeofday (&tod, NULL); return ((double)tod.tv_sec * 1000.0 + (double)tod.tv_usec / 1000.0); }/* * read rgb image from v4l device 從v4l設(shè)備獲取rgb圖像 * 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, *convmap; //map指向抓到的圖片所存空間 int len; int bytes = 3; //比特每像素 if (palette == VIDEO_PALETTE_GREY) //若為灰度圖象 bytes = 1; /* bytes per pixel */ 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)"); //ioctl函數(shù)功能?? return (NULL); } } map = malloc (width * height * bytes); //分配空間 len = read (dev, map, width * height * bytes); //從v41設(shè)備讀取圖像信息到map所指向的空間 if (len <= 0) { free (map); return (NULL); } *size = 0; if (palette == VIDEO_PALETTE_YUV420P) { convmap = malloc ( width * height * bytes ); v4l_yuv420p2rgb (convmap, map, width, height, bytes * 8);//顏色空間的轉(zhuǎn)換 memcpy (map, convmap, (size_t) width * height * bytes); //將convmap指向的圖像的值復(fù)制
//到map指向的一段連續(xù)的空間 free (convmap); } else if (palette == VIDEO_PALETTE_YUV422P) { convmap = malloc ( width * height * bytes ); v4l_yuv422p2rgb (convmap, map, width, height, bytes * 8); memcpy (map, convmap, (size_t) width * height * bytes); free (convmap); } return (map); //返回map,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 (palette == VIDEO_PALETTE_YUV420P) { if (verbose) fprintf (stderr, "converting from YUV to RGB\n"); convmap = malloc ( width * height * bytes ); v4l_yuv420p2rgb (convmap, map, width, height, bytes * 8); memcpy (map, convmap, (size_t) width * height * bytes); free (convmap); } else if (palette == VIDEO_PALETTE_YUV422P) { if (verbose) fprintf (stderr, "converting from YUV to RGB\n"); convmap = malloc ( width * height * bytes ); v4l_yuv422p2rgb (convmap, map, width, height, bytes * 8); memcpy (map, convmap, (size_t) width * height * bytes); free (convmap); } return (map); if (verbose) fprintf (stderr, "got picture\n");}/*將get_image函數(shù)抓到的圖片壓縮成不同的格式 */voidput_image_jpeg (FILE *out, char *image, int width, int height, int quality, int palette){#ifdef HAVE_LIBJPEG int y, x, line_width; JSAMPROW row_ptr[1]; struct jpeg_compress_struct cjpeg; struct jpeg_error_mgr jerr; char *line; line = malloc (width * 3); if (!line) return; if (verbose) fprintf (stderr, "writing JPEG data\n"); cjpeg.err = jpeg_std_error(&jerr); jpeg_create_compress (&cjpeg); //創(chuàng)建jpge壓縮結(jié)構(gòu)體 cjpeg.image_width = width; cjpeg.image_height= height; if (palette == VIDEO_PALETTE_GREY) { cjpeg.input_components = 1; //若為灰度圖象,每像素一個bit cjpeg.in_color_space = JCS_GRAYSCALE; // jpeg_set_colorspace (&cjpeg, JCS_GRAYSCALE); } else { cjpeg.input_components = 3; //若不是灰度圖象,每像素3個bit cjpeg.in_color_space = JCS_RGB; //rgb的顏色空間 } jpeg_set_defaults (&cjpeg); jpeg_set_quality (&cjpeg, quality, TRUE); cjpeg.dct_method = JDCT_FASTEST; jpeg_stdio_dest (&cjpeg, out); jpeg_start_compress (&cjpeg, TRUE); row_ptr[0] = line; if (palette == VIDEO_PALETTE_GREY) { line_width = width; for ( y = 0; y < height; y++) { row_ptr[0] = image; jpeg_write_scanlines (&cjpeg, row_ptr, 1); image += line_width; } } else { line_width = width * 3; for ( y = 0; y < height; y++) { for (x = 0; x < line_width; x+=3) { line[x] = image[x+2]; line[x+1] = image[x+1]; line[x+2] = image[x]; } jpeg_write_scanlines (&cjpeg, row_ptr, 1); image += line_width; } } jpeg_finish_compress (&cjpeg); jpeg_destroy_compress (&cjpeg); free (line);#endif}/* * write png image to stdout */voidput_image_png (FILE *out, char *image, int width, int height, int palette){#ifdef HAVE_LIBPNG int y, bpp; char *p; png_infop info_ptr; png_structp png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return; info_ptr = png_create_info_struct (png_ptr); if (!info_ptr) return; png_init_io (png_ptr, out); if (palette == VIDEO_PALETTE_GREY) { png_set_IHDR (png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); bpp = 1; } else { png_set_IHDR (png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); bpp = 3; } png_set_bgr (png_ptr); png_write_info (png_ptr, info_ptr); p = image; for (y = 0; y < height; y++) { png_write_row (png_ptr, p); p += width * bpp; } png_write_end (png_ptr, info_ptr);#endif}/* * write ppm image to stdout / file */voidput_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");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -