在QT中的摄像头程序
2014-04-25 10:47
211 查看
#include "hello.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/videodev2.h>
#include <qapplication.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qtooltip.h>
#include <qpainter.h>
#include <qimage.h>
#define WIDTH 160
#define HEIGHT 120
#define FRAME_COUNT 1 //?建?????
#define FRAME_IDLE 60
typedef struct VideoBuffer //定义一个结构体来映射每个缓冲帧
{
void *start;
size_t length;
}VideoBuffer;
static int fd;
static VideoBuffer *buffers = NULL;
static unsigned int numBufs = 0;
static int v4l2_get_capability(void)//读取设备拥有的功能
{
struct v4l2_capability cap;
if (::ioctl (fd, VIDIOC_QUERYCAP, &cap) == -1)
{
printf("Get camara capability is fail.\n");
return -1;
}
printf("camara driver: %s\n", cap.driver);
printf("camara card: %s\n", cap.card);
printf("camara bus info: %s\n", cap.bus_info);
printf("camara version: %d\n", cap.version);
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) //是否支持图像获取
{
printf("Camara does not support VIDEO CAPTURE.\n");
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) //I/O的读写控制流
{
printf("Camara does not support STREAMING.\n");
return -1;
}
return 0;
/*
相关结构体:
structv4l2_capability
{
__u8 driver[16]; // 驱动名字
__u8 card[32]; // 设备名字
__u8bus_info[32]; // 设备在系统中的位置
__u32 version; // 驱动版本号
__u32capabilities; // 设备支持的操作
__u32reserved[4]; // 保留字段
};
capabilities 常用值:
V4L2_CAP_VIDEO_CAPTURE // 是否支持图像获取
Values for 'capabilities' field //内核驱动中定义的视频驱动的能力
#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device
#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device
#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay
#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device
#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay
#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek
#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support
#define V4L2_CAP_RADIO 0x00040000 /* is a radio device *
#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator *
#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls *
#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O *
#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls *
} */
static int v4l2_set_fmt(void)//设置视频帧格式,包括帧的点阵格式,宽度和高度
{
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = WIDTH;
fmt.fmt.pix.height = HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (::ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)//检查是否支持V4L2_PIX_FMT_MJPEG 格式
{
printf("Camara set fmt is errror.\n");
return -1;
}
return 0;
}
/*
VIDIOC_TRY_FMT
int ioctl(intfd, int request, struct v4l2_format *argp);
structv4l2_format
{
enumv4l2_buf_type type;// 帧类型,应用程序设置
union fmt
{
structv4l2_pix_format pix;// 视频设备使用
structv4l2_window win;
structv4l2_vbi_format vbi;
structv4l2_sliced_vbi_format sliced;
__u8raw_data[200];
};
};
structv4l2_pix_format
{
__u32 width; // 帧宽,单位像素
__u32 height; // 帧高,单位像素
__u32pixelformat; // 帧格式
enum v4l2_fieldfield;
__u32bytesperline;
__u32 sizeimage;
enumv4l2_colorspace colorspace;
__u32 priv;
};
*/
static int v4l2_set_memory(void)
{
struct v4l2_requestbuffers req;
enum v4l2_buf_type type; //enum v4l2_buf_type type; //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
struct v4l2_buffer buf;
// 向设备申请缓冲区
/*
structv4l2_requestbuffers
{
__u32 count; // 缓冲区内缓冲帧的数目
enumv4l2_buf_type type; // 缓冲帧数据格式
enum v4l2_memorymemory; // 区别是内存映射还是用户指针方式
__u32 reserved[2];
};
*/
memset(&req, 0, sizeof (req));
req.count = FRAME_COUNT;////缓存数量,也就是说在缓存队列里保持多少张照片 申请一个拥有FRAME_COUNT个缓冲帧的缓冲区
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (::ioctl(fd, VIDIOC_REQBUFS, &req) < 0)
{
printf("VIDIOC_REQBUFS failed\n");
return -1;
}
// 使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,
//然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:
// 获取缓冲帧的地址,长度:
/*
struct v4l2_buffer
{
__u32 index; //buffer 序号
enumv4l2_buf_type type; //buffer 类型
__u32 byteused; //buffer 中已使用的字节数
__u32 flags; // 区分是MMAP 还是USERPTR
enum v4l2_fieldfield;
struct timevaltimestamp;// 获取第一个字节时的系统时间
structv4l2_timecode timecode;
__u32 sequence;// 队列中的序号
enum v4l2_memorymemory;//IO 方式,被应用程序设置
union m
{
__u32 offset;// 缓冲帧地址,只对MMAP 有效
unsigned longuserptr;
};
__u32 length;// 缓冲帧长度
__u32 input;
__u32 reserved;
};
*/
//将FRAME_COUNT个已申请到的缓冲帧映射到应用程序,用buffers 指针记录。
buffers = (VideoBuffer *)calloc(req.count, sizeof(*buffers));
// 映射
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
// 查询序号为numBufs的缓冲区,得到其起始物理地址和大小
if (::ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) // 读取缓存
return -1;
buffers[numBufs].length = buf.length;
// 转换成相对地址
//映射内存
buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);//返回所分配的内存空间的首地址。
/*
void *mmap(void*addr, size_t length, int prot, int flags, int fd, off_t offset);
//addr 映射起始地址,一般为NULL ,让内核自动选择
//length 被映射内存块的长度
//prot 标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE
//flags 确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE
//fd,offset, 确定被映射的内存地址
返回成功映射后的地址,不成功返回MAP_FAILED ((void*)-1);*/
if (buffers[numBufs].start == MAP_FAILED)
return -1;
//VIDIOC_QBUF// 把帧放入队列
//VIDIOC_DQBUF// 从队列中取出帧
if (::ioctl(fd, VIDIOC_QBUF, &buf) == -1)// 放入缓存队列
return -1;
}
// 在开始之前,还应当把缓冲帧放入缓冲队列:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (::ioctl (fd, VIDIOC_STREAMON, &type) < 0) //开始视屏流数据的采集
{
printf("VIDIOC_STREAMON error\n");
return -1;
}
return 0;
}
//获取一帧并处理
static int v4l2_read_pic(int index)
{
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = index;
//VIDIOC_DQBUF 从队列中取出帧
if (::ioctl(fd, VIDIOC_DQBUF, &buf) == -1)
return -1;
/*图像处理
process_image(buffers[buf.index].start); */
//将取出的缓冲帧放回缓冲区
if (::ioctl(fd, VIDIOC_QBUF, &buf) == -1)
return -1;
return 0;
}
static int v4l2_init(const char *dev_name)
{
// 鎵撳紑video device
fd = ::open(dev_name, O_RDWR);//打开视屏设备文件
if (fd == -1)
{
printf("open camera is fail.\n");
return -1;
}
//查询设备属性
if (v4l2_get_capability())
return -1;
// 设置帧格式
if (v4l2_set_fmt())
return -1;
// 申请和管理缓冲区
if (v4l2_set_memory())
return -1;
return 0;
}
MyHelloForm::MyHelloForm( QWidget* parent, const char* name, WFlags fl)
:HelloBaseForm(parent, name, fl)
{
if (v4l2_init("/dev/video0"))
{
printf("v4l2 init is error!\n");
emit(close_signal());
}
connect (this, SIGNAL(close_signal()), this, SLOT(camara_quit()));
connect (this, SIGNAL(quit_signal()), qApp, SLOT(quit()));
connect (CloseButton, SIGNAL(clicked()), this, SLOT(camara_quit()));
connect (SnapButton, SIGNAL(clicked()), this, SLOT(camara_snap()));
timer = new QTimer(this);
connect (timer, SIGNAL(timeout()), this, SLOT(showMe()));
timer->start(FRAME_IDLE);
}
MyHelloForm::~MyHelloForm()
{
}
void MyHelloForm::showMe()
{
QPainter painter(this);
QImage image;
if (v4l2_read_pic(0))
return;
image.loadFromData((uchar *)buffers[0].start, buffers[0].length, "JPEG");
painter.drawImage(40, 30, image, 0, 0, WIDTH, HEIGHT);//drawImage是QPainter的一个方法,
// 这里的意思是将image对象放到窗口的(40,30)位置,亦即左上角,最后两个数字是指定的大小。
}
void MyHelloForm::camara_snap()
{
int pic_fd, i;
time_t t = time(NULL);
char name[50], *pic_name, *dir_name = "/root/Documents/";
size_t len, len1;
timer->stop();
pic_name = ctime(&t);//我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,两者的返回值都是char*型的字符串
len = strlen(pic_name);
len1 = strlen(dir_name);
dir_name = strcpy(name, dir_name);
for (i=0; i<len-1; i++)
dir_name[len1+i] = pic_name[i];
dir_name[len1+len-1] = '\0';
dir_name = strcat(dir_name, ".jpg");
printf("dir_name: %s\n", dir_name);
pic_fd = ::open(dir_name, O_RDWR | O_CREAT, S_IRWXU);
if (pic_fd == -1)
{
printf("save jpg file fail\n");
return;
}
::write(pic_fd, buffers[0].start, buffers[0].length);
::close(pic_fd);
sleep(1);
timer->start(FRAME_IDLE);
}
void MyHelloForm::camara_quit()
{
munmap(buffers[0].start, FRAME_COUNT*buffers[0].length);
::close(fd);
timer->stop();
emit(quit_signal());
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/videodev2.h>
#include <qapplication.h>
#include <qlabel.h>
#include <qpushbutton.h>
#include <qtooltip.h>
#include <qpainter.h>
#include <qimage.h>
#define WIDTH 160
#define HEIGHT 120
#define FRAME_COUNT 1 //?建?????
#define FRAME_IDLE 60
typedef struct VideoBuffer //定义一个结构体来映射每个缓冲帧
{
void *start;
size_t length;
}VideoBuffer;
static int fd;
static VideoBuffer *buffers = NULL;
static unsigned int numBufs = 0;
static int v4l2_get_capability(void)//读取设备拥有的功能
{
struct v4l2_capability cap;
if (::ioctl (fd, VIDIOC_QUERYCAP, &cap) == -1)
{
printf("Get camara capability is fail.\n");
return -1;
}
printf("camara driver: %s\n", cap.driver);
printf("camara card: %s\n", cap.card);
printf("camara bus info: %s\n", cap.bus_info);
printf("camara version: %d\n", cap.version);
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) //是否支持图像获取
{
printf("Camara does not support VIDEO CAPTURE.\n");
return -1;
}
if (!(cap.capabilities & V4L2_CAP_STREAMING)) //I/O的读写控制流
{
printf("Camara does not support STREAMING.\n");
return -1;
}
return 0;
/*
相关结构体:
structv4l2_capability
{
__u8 driver[16]; // 驱动名字
__u8 card[32]; // 设备名字
__u8bus_info[32]; // 设备在系统中的位置
__u32 version; // 驱动版本号
__u32capabilities; // 设备支持的操作
__u32reserved[4]; // 保留字段
};
capabilities 常用值:
V4L2_CAP_VIDEO_CAPTURE // 是否支持图像获取
Values for 'capabilities' field //内核驱动中定义的视频驱动的能力
#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device
#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device
#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay
#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device
#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay
#define V4L2_CAP_HW_FREQ_SEEK 0x00000400 /* Can do hardware frequency seek
#define V4L2_CAP_RDS_OUTPUT 0x00000800 /* Is an RDS encoder
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support
#define V4L2_CAP_RADIO 0x00040000 /* is a radio device *
#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator *
#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls *
#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O *
#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls *
} */
static int v4l2_set_fmt(void)//设置视频帧格式,包括帧的点阵格式,宽度和高度
{
struct v4l2_format fmt;
memset(&fmt, 0, sizeof(fmt));
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = WIDTH;
fmt.fmt.pix.height = HEIGHT;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (::ioctl(fd, VIDIOC_S_FMT, &fmt) == -1)//检查是否支持V4L2_PIX_FMT_MJPEG 格式
{
printf("Camara set fmt is errror.\n");
return -1;
}
return 0;
}
/*
VIDIOC_TRY_FMT
int ioctl(intfd, int request, struct v4l2_format *argp);
structv4l2_format
{
enumv4l2_buf_type type;// 帧类型,应用程序设置
union fmt
{
structv4l2_pix_format pix;// 视频设备使用
structv4l2_window win;
structv4l2_vbi_format vbi;
structv4l2_sliced_vbi_format sliced;
__u8raw_data[200];
};
};
structv4l2_pix_format
{
__u32 width; // 帧宽,单位像素
__u32 height; // 帧高,单位像素
__u32pixelformat; // 帧格式
enum v4l2_fieldfield;
__u32bytesperline;
__u32 sizeimage;
enumv4l2_colorspace colorspace;
__u32 priv;
};
*/
static int v4l2_set_memory(void)
{
struct v4l2_requestbuffers req;
enum v4l2_buf_type type; //enum v4l2_buf_type type; //数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
struct v4l2_buffer buf;
// 向设备申请缓冲区
/*
structv4l2_requestbuffers
{
__u32 count; // 缓冲区内缓冲帧的数目
enumv4l2_buf_type type; // 缓冲帧数据格式
enum v4l2_memorymemory; // 区别是内存映射还是用户指针方式
__u32 reserved[2];
};
*/
memset(&req, 0, sizeof (req));
req.count = FRAME_COUNT;////缓存数量,也就是说在缓存队列里保持多少张照片 申请一个拥有FRAME_COUNT个缓冲帧的缓冲区
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (::ioctl(fd, VIDIOC_REQBUFS, &req) < 0)
{
printf("VIDIOC_REQBUFS failed\n");
return -1;
}
// 使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,
//然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:
// 获取缓冲帧的地址,长度:
/*
struct v4l2_buffer
{
__u32 index; //buffer 序号
enumv4l2_buf_type type; //buffer 类型
__u32 byteused; //buffer 中已使用的字节数
__u32 flags; // 区分是MMAP 还是USERPTR
enum v4l2_fieldfield;
struct timevaltimestamp;// 获取第一个字节时的系统时间
structv4l2_timecode timecode;
__u32 sequence;// 队列中的序号
enum v4l2_memorymemory;//IO 方式,被应用程序设置
union m
{
__u32 offset;// 缓冲帧地址,只对MMAP 有效
unsigned longuserptr;
};
__u32 length;// 缓冲帧长度
__u32 input;
__u32 reserved;
};
*/
//将FRAME_COUNT个已申请到的缓冲帧映射到应用程序,用buffers 指针记录。
buffers = (VideoBuffer *)calloc(req.count, sizeof(*buffers));
// 映射
for (numBufs = 0; numBufs < req.count; numBufs++)
{
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
// 查询序号为numBufs的缓冲区,得到其起始物理地址和大小
if (::ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) // 读取缓存
return -1;
buffers[numBufs].length = buf.length;
// 转换成相对地址
//映射内存
buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);//返回所分配的内存空间的首地址。
/*
void *mmap(void*addr, size_t length, int prot, int flags, int fd, off_t offset);
//addr 映射起始地址,一般为NULL ,让内核自动选择
//length 被映射内存块的长度
//prot 标志映射后能否被读写,其值为PROT_EXEC,PROT_READ,PROT_WRITE,PROT_NONE
//flags 确定此内存映射能否被其他进程共享,MAP_SHARED,MAP_PRIVATE
//fd,offset, 确定被映射的内存地址
返回成功映射后的地址,不成功返回MAP_FAILED ((void*)-1);*/
if (buffers[numBufs].start == MAP_FAILED)
return -1;
//VIDIOC_QBUF// 把帧放入队列
//VIDIOC_DQBUF// 从队列中取出帧
if (::ioctl(fd, VIDIOC_QBUF, &buf) == -1)// 放入缓存队列
return -1;
}
// 在开始之前,还应当把缓冲帧放入缓冲队列:
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (::ioctl (fd, VIDIOC_STREAMON, &type) < 0) //开始视屏流数据的采集
{
printf("VIDIOC_STREAMON error\n");
return -1;
}
return 0;
}
//获取一帧并处理
static int v4l2_read_pic(int index)
{
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = index;
//VIDIOC_DQBUF 从队列中取出帧
if (::ioctl(fd, VIDIOC_DQBUF, &buf) == -1)
return -1;
/*图像处理
process_image(buffers[buf.index].start); */
//将取出的缓冲帧放回缓冲区
if (::ioctl(fd, VIDIOC_QBUF, &buf) == -1)
return -1;
return 0;
}
static int v4l2_init(const char *dev_name)
{
// 鎵撳紑video device
fd = ::open(dev_name, O_RDWR);//打开视屏设备文件
if (fd == -1)
{
printf("open camera is fail.\n");
return -1;
}
//查询设备属性
if (v4l2_get_capability())
return -1;
// 设置帧格式
if (v4l2_set_fmt())
return -1;
// 申请和管理缓冲区
if (v4l2_set_memory())
return -1;
return 0;
}
MyHelloForm::MyHelloForm( QWidget* parent, const char* name, WFlags fl)
:HelloBaseForm(parent, name, fl)
{
if (v4l2_init("/dev/video0"))
{
printf("v4l2 init is error!\n");
emit(close_signal());
}
connect (this, SIGNAL(close_signal()), this, SLOT(camara_quit()));
connect (this, SIGNAL(quit_signal()), qApp, SLOT(quit()));
connect (CloseButton, SIGNAL(clicked()), this, SLOT(camara_quit()));
connect (SnapButton, SIGNAL(clicked()), this, SLOT(camara_snap()));
timer = new QTimer(this);
connect (timer, SIGNAL(timeout()), this, SLOT(showMe()));
timer->start(FRAME_IDLE);
}
MyHelloForm::~MyHelloForm()
{
}
void MyHelloForm::showMe()
{
QPainter painter(this);
QImage image;
if (v4l2_read_pic(0))
return;
image.loadFromData((uchar *)buffers[0].start, buffers[0].length, "JPEG");
painter.drawImage(40, 30, image, 0, 0, WIDTH, HEIGHT);//drawImage是QPainter的一个方法,
// 这里的意思是将image对象放到窗口的(40,30)位置,亦即左上角,最后两个数字是指定的大小。
}
void MyHelloForm::camara_snap()
{
int pic_fd, i;
time_t t = time(NULL);
char name[50], *pic_name, *dir_name = "/root/Documents/";
size_t len, len1;
timer->stop();
pic_name = ctime(&t);//我们可以通过asctime()函数和ctime()函数将时间以固定的格式显示出来,两者的返回值都是char*型的字符串
len = strlen(pic_name);
len1 = strlen(dir_name);
dir_name = strcpy(name, dir_name);
for (i=0; i<len-1; i++)
dir_name[len1+i] = pic_name[i];
dir_name[len1+len-1] = '\0';
dir_name = strcat(dir_name, ".jpg");
printf("dir_name: %s\n", dir_name);
pic_fd = ::open(dir_name, O_RDWR | O_CREAT, S_IRWXU);
if (pic_fd == -1)
{
printf("save jpg file fail\n");
return;
}
::write(pic_fd, buffers[0].start, buffers[0].length);
::close(pic_fd);
sleep(1);
timer->start(FRAME_IDLE);
}
void MyHelloForm::camara_quit()
{
munmap(buffers[0].start, FRAME_COUNT*buffers[0].length);
::close(fd);
timer->stop();
emit(quit_signal());
}
相关文章推荐
- qt 摄像头程序
- 基于QT和opencv的摄像头(本地图片)读取并输出程序
- 用qt的qml写的安卓摄像头程序
- arm版qt opencv程序自启动 触摸屏可以用但不能初始化摄像头
- Linux+QT+OpenCv摄像头调试心得(2)----点击退出关闭窗体,提示“程序异常终止”
- 发布的Qt程序如何才能正常显示图片
- 【笔记】Qt程序在Windows、OS X、CentOS、Ubuntu下的打包处理
- 在Qt编写的程序中打开文件夹 .
- VS编写Qt界面程序如何不出现控制台
- 在没有安装QT的电脑上运行QT程序常见的问题
- Qt调用默认程序打开文件
- QT中用Qpainter的drawText方法程序crash的可能原因
- 简单的QT绘图程序
- [ARM Linux] [Qt] 移植Qt程序到ARM Linux上 (包括如何构建专业的PDA界面、phone界面)
- Qt程序发布
- Qt之程序最小化托盘显示及操作
- 让你的 Qt 桌面程序看上去更加 native(四):style sheet
- qt 无法启动此程序 因为计算机中丢失 XXX.dll.尝试重新安装该程序以解决此问题
- QT程序中文显示的其他方法
- C#程序对本地摄像头的调用程序