涉及內容:
1、v4l2操作攝像頭
2、RGB565轉BMP(RGB16)文件
參考代碼:
#include <sys/time.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <jpeglib.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include "videodev2.h"
#include <linux/fb.h>
#include "jpeglib.h"
#define CTRL_NUM 100
#define WIDTH 480
#define HEIGHT 272
//文件頭
struct tagBITMAPFILEHEADER{
unsigned long bfSize;
unsigned long bfLeft;
unsigned long bfOffBits;
};
// bmp圖像的位圖信息頭
struct tagBITMAPINFOHEADER{
unsigned long biSize;
unsigned long bmpWidth;
unsigned long bmpHeight;
unsigned short biPlanes;
unsigned short bicolors;
unsigned long isCompressed;
unsigned long biMapSize;
unsigned long biHorizontal;
unsigned long biVertical;
unsigned long biusedcolors;
unsigned long biimportcolors;
};
#define V4L2_DEV_NODE "/dev/video1"
#define FB_DEV_NODE "/dev/fb0"
typedef struct v4l2_input V_INPUT;
typedef struct v4l2_format V_FORMAT;
typedef struct v4l2_fmtdesc V_FMTDESC;
typedef struct v4l2_queryctrl V_QRYCTRL;
typedef struct fb_var_screeninfo F_VINFO;
#define V4L2_FMT_IN 0
#define V4L2_FMT_OUT 1
unsigned char *preview_buf;
static void writebmp(int data_fd){
int i,j,k,size;
int ret;
unsigned char *buf1 = (unsigned char *)malloc(sizeof(unsigned char) * 480*272*2);
memcpy(buf1, preview_buf, 480*272*2);
unsigned short buf[WIDTH*HEIGHT]={0};
printf("Write buf[i*WIDTH+k] begin!\n");
for(i=0;i<HEIGHT;i++)
{
for(j=0;j<WIDTH;j++)
{
*(buf+i*WIDTH+j)= (buf1[i*WIDTH*2+j*2])|(buf1[i*WIDTH*2+j*2+1]<<8);
//if(i<1)
// printf("(%d,%d,0x%4x)\n",i,j,*(buf+i*WIDTH+j));
}
}
printf("Write buf[i*WIDTH+k] end!\n");
unsigned short bmp[WIDTH*HEIGHT];
struct tagBITMAPFILEHEADER bfhead;
struct tagBITMAPINFOHEADER binfohead;
size=HEIGHT*WIDTH;
bfhead.bfSize=0x36+size*2;
bfhead.bfLeft=0;
bfhead.bfOffBits=0x36;
binfohead.biSize=0x28;
binfohead.bmpWidth=WIDTH;
binfohead.bmpHeight=HEIGHT;
binfohead.biPlanes=1;
binfohead.bicolors=0x10;
binfohead.isCompressed=0;
binfohead.biMapSize=size*2;
binfohead.biHorizontal=0x0b13;
binfohead.biVertical=0x0b13;
binfohead.biusedcolors=0;
binfohead.biimportcolors=0;
for(i=0;i<HEIGHT;i++)
for(j=0;j<WIDTH;j++)
*(bmp+i*WIDTH+j)=((buf[(HEIGHT-i)*WIDTH-WIDTH+j]&0xf800)>>1)|((buf[(HEIGHT-i)*WIDTH-WIDTH+j]&0x07c0)>>1)|((buf[(HEIGHT-i)*WIDTH-WIDTH+j]&0x1f));
//翻轉圖像
//for (i=HEIGHT; i>=0;i--)
// for(j=WIDTH;j>=0;j--)
// *(bmp+i*WIDTH+j)=((buf[i*WIDTH+j]&0xf800)>>1)|((buf[i*WIDTH+j]&0x07c0)>>1)|((buf[i*WIDTH+j]&0x1f));
write(data_fd,"BM",2);
i=write(data_fd,&bfhead,sizeof(struct tagBITMAPFILEHEADER));
printf("Write filehead %dbytes\n",i);
i=write(data_fd,&binfohead,sizeof(struct tagBITMAPINFOHEADER));
printf("Write infohead %dbytes\n",i);
i=write(data_fd,bmp,size*2);
printf("Write bitmap %dbytes\n",i);
lseek(data_fd,SEEK_SET,4);
}
int main(void)
{
int v4l2_fd = -1;
int fb_fd = -1;
int n=0;
__u8 *fb_buf;
__u32 screensize;
V_FORMAT fmt;
struct v4l2_capability caminfo;
v4l2_fd = open(V4L2_DEV_NODE, O_RDWR);
if (v4l2_fd < 0) {
printf(" open video ERR\n");
}
fb_fd = open(FB_DEV_NODE, O_RDWR);
if (fb_fd < 0) {
printf(" open FB ERR\n");
}
screensize = 480 * 272 * 16 / 8;
fb_buf = (__u8 *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
fb_fd, 0);
if ((int)fb_buf == -1) {
printf("Error: failed to map framebuffer device to memory.\n");
close(fb_fd);
return -1;
}
if((n =(ioctl(v4l2_fd, VIDIOC_QUERYCAP, &caminfo)))<0)
printf("Error: failed to get camera info.%d\n",n);
//設置圖象模式
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 480;
fmt.fmt.pix.height = 272;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB565;
fmt.fmt.pix.priv = V4L2_FMT_OUT;
if((ioctl(v4l2_fd, VIDIOC_S_FMT, &fmt))<0)
printf("Error: failed to set video format.\n");
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if((ioctl(v4l2_fd, VIDIOC_STREAMON, &type))<0)
printf("start to get pic %d\n",(int)fmt.fmt.pix.sizeimage);
int ii = 0;
while(1){
n=read(v4l2_fd, fb_buf, 480*272*2);
if (ii == 0 && n > 0) {
int data_fd=-1;
printf("read Data Length:%d\n", n);
preview_buf = malloc(n);
memcpy(preview_buf, fb_buf, n);
char bmpfilename[30];
sprintf(bmpfilename, "/sdcard/photo%d.bmp",1);
if((data_fd = open(bmpfilename,O_CREAT|O_RDWR,0777))<0){
printf("Error: failed to creat photo.bmp.\n");
return 0;
}
printf("bmpfilename is %s\n",bmpfilename);
writebmp(data_fd);
if(data_fd>0)
close(data_fd);
free(preview_buf);
ii = 1;
}
}
}