涉及内容:
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; } } }