首先我使用的linux系统是字符界面的,很想找一个最简单的USB摄像头程序进行摄像头测试。可是找了半天不是不能用就是太复杂,不方便测试也不方便入门学习。国外的要收费,国内的好不容易找到一个,还有BUG,又用不了。
找到了L4V2 api官方测试程序,弄了半天总算有点明白了。稍微做了改动。
这个程序是使用YUV格式保存,并且通过stdio输出,这样做的目的是方便重定向到下一个转换程序。但是对于着急需要测试和入门学习的人来说,就是隔靴搔痒了。
所以,我将程序稍微修改了一下。当只要求拍摄一幅图片时,就自动将其保存为bmp文件,这样就可以快速对摄像头进行测试。
这个程序没有库的依赖,是最最简单和轻量级的。
这里我的摄像头是video4,其实也可以单独指定。
v4l2grab.h
#ifndef __V4LGRAB_H__
#define __V4LGRAB_H__
#include <stdio.h>
#define FALSE 0
#define TRUE 1
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
/**/
#pragma pack(push)
#pragma pack(2)
typedef struct tagBITMAPFILEHEADER{
WORD bfType; // the flag of bmp, value is "BM"
DWORD bfSize; // size BMP file ,unit is bytes
DWORD bfReserved; // 0
DWORD bfOffBits; // must be 54
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // must be 0x28
DWORD biWidth; //
DWORD biHeight; //
WORD biPlanes; // must be 1
WORD biBitCount; //
DWORD biCompression; //
DWORD biSizeImage; //
DWORD biXPelsPerMeter; //
DWORD biYPelsPerMeter; //
DWORD biClrUsed; //
DWORD biClrImportant; //
}BITMAPINFOHEADER;
typedef struct tagRGBQUAD{
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
}RGBQUAD;
#pragma pack(pop)
//if successful return 1,or else return 0
int openVideo();
int closeVideo();
#endif //__V4LGRAB_H___
----------------------.c代码分割线--------
/*
* V4L2 video capture example
*
* This program can be used and distributed without restrictions.
*
* This program is provided with the V4L2 API
* see http://linuxtv.org/docs.php for more information
* http://www.linuxtv.org/downloads/v4l-dvb-apis/capture-example.html
* modify by mayy02@163.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include "v4l2grab.h"
#define CLEAR(x) memset(&(x), 0, sizeof(x))
enum io_method {
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
};
struct buffer {
void *start;
size_t length;
};
static char *dev_name;
static enum io_method io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer *buffers;
static unsigned int n_buffers;
static int out_buf;
static int force_format;
static int frame_count = 70;
static void errno_exit(const char *s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
static int xioctl(int fh, int request, void *arg)
{
int r;
do {
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
int yuyv_2_rgb888(unsigned char *inp, int size, unsigned char *outp)
{
int i,j;
unsigned char y1,y2,u,v;
int r1,g1,b1,r2,g2,b2;
for(i=0;i<480;i++)
{
for(j=0;j<320;j++)
{
y1 = *( inp + (i*320+j)*4);
u = *( inp + (i*320+j)*4 + 1);
y2 = *( inp + (i*320+j)*4 + 2);
v = *( inp + (i*320+j)*4 + 3);
r1 = y1 + 1.042*(v-128);
g1 = y1 - 0.34414*(u-128) - 0.71414*(v-128);
b1 = y1 + 1.772*(u-128);
r2 = y2 + 1.042*(v-128);
g2 = y2 - 0.34414*(u-128) - 0.71414*(v-128);
b2 = y2 + 1.772*(u-128);
if(r1>255)
r1 = 255;
else if(r1<0)
r1 = 0;
if(b1>255)
b1 = 255;
else if(b1<0)
b1 = 0;
if(g1>255)
g1 = 255;
else if(g1<0)
g1 = 0;
if(r2>255)
r2 = 255;
else if(r2<0)
r2 = 0;