⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera_adv.c

📁 嵌入式Linux下采集中星微301系列摄像头数据,并直接在屏幕上绘出图片(在没有GUI的环境下)
💻 C
字号:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
//#include <ctype.h>
#include <sys/mman.h>
//#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/videodev.h>
#include <errno.h>
#include "jpeglib.h"
#include <setjmp.h>
#include "bitmap_convert.h"

#define CAMERA_DEV "/dev/video0"

struct video4linux_struct
{
	int dev;
	struct video_window     win;
	struct video_capability caps;
	struct video_picture    pic;
	struct video_mbuf       mbuf;
	struct video_mmap       mmap;
	
	unsigned char *map;
	char *buffer;
	int frame;
	int framestat[2];
};	
/*
struct spca5xx_struct
{

};
*/


unsigned char * image_buffer;	/* Points to large array of R,G,B-order data */
int image_height;	/* Number of rows in image */
int image_width;		/* Number of columns in image */

//================[camera]================
//================[camera]================
//================[camera]================
int func_camera_init(struct video4linux_struct *v4l_info)
{
	//----------[open-device]-------------------------
	v4l_info->dev=open(CAMERA_DEV,O_RDWR);
	if (v4l_info->dev < 0)
	{	printf("open CAMERA_DEV : error\n"); return -1; }
	else
	{	printf("open CAMERA_DEV : ok \n");  }


	//---------[capability]-------------[获得摄像头属性]
	ioctl(v4l_info->dev,VIDIOCGCAP,&v4l_info->caps);
  	printf("1.VIDIOCGCAP %s %d %d %d %d type: %d\n",
			v4l_info->caps.name,
			v4l_info->caps.maxwidth,
			v4l_info->caps.maxheight,
			v4l_info->caps.minwidth,
			v4l_info->caps.minheight,
			v4l_info->caps.type);

	//----------[Capture Windows]-------------------
	ioctl(v4l_info->dev , VIDIOCGWIN , &v4l_info->win);
	printf("2.VIDIOCGWIN %d %d %d %d %d \n",
			v4l_info->win.x,
			v4l_info->win.y,
			v4l_info->win.width,
			v4l_info->win.height,
			v4l_info->win.chromakey);

	//-----------[picture]---------------[设备采集的图象的各种属性]
	ioctl(v4l_info->dev , VIDIOCGPICT , &v4l_info->pic);
	printf("3.VIDIOCGPICT : brightness[%d] hue[%d] colour[%d] contrast[%d]\n   whiteness[%d] depth[%d] palette[%d]\n",
			v4l_info->pic.brightness,
			v4l_info->pic.hue,
			v4l_info->pic.colour,
			v4l_info->pic.contrast,
			v4l_info->pic.whiteness,
			v4l_info->pic.depth,
			v4l_info->pic.palette);
//	&v4l_info->pic.colour=65535;//65535//16777215
//	&v4l_info->pic.depth=8;//16//24
//	&v4l_info->pic.palette=VIDEO_PALETTE_RGB565;
//	ioctl(v4l_info->dev,VIDIOCSPICT,&v4l_info->pic); //SET video_picture
//	printf("3.VIDIOCGPICT [set]:brightness[%d] hue[%d] colour[%d] contrast[%d]\n   whiteness[%d] depth[%d] palette[%d]\n",vid_pic.brightness,vid_pic.hue,vid_pic.colour,vid_pic.contrast,vid_pic.whiteness,vid_pic.depth,vid_pic.palette);			
	
	//-------------[mbuf]--------------[利用mmap进行映射的帧的信息]
	ioctl(v4l_info->dev ,VIDIOCGMBUF, &v4l_info->mbuf);
	printf("4.video_mbuf : size[%d] frames[%d] offsets0[%d] offsets1[%d] \n\n",
			v4l_info->mbuf.size ,
			v4l_info->mbuf.frames,
			v4l_info->mbuf.offsets[0],
			v4l_info->mbuf.offsets[1]);


	//------------[video_mmap]-----[用于mmap]
	/* struct video_mmap
	 *	{
	 *		unsigned	int frame;		
	 *		int		height,width;
	 *		unsigned	int format;		// should be VIDEO_PALETTE_*
	 *	};
	 */
	 /* #define VIDEO_PALETTE_RAW_JPEG  20 (spca5xx.h)
	  * #define VIDEO_PALETTE_JPEG 21
	  */
	v4l_info->mmap.format=VIDEO_PALETTE_RGB565;//21;//vid_pic.palette//VIDEO_PALETTE_RGB24//VIDEO_PALETTE_RGB565
	v4l_info->mmap.width=320;
	v4l_info->mmap.height=240;
	v4l_info->framestat[0] =v4l_info->framestat[1] = 0;  
	v4l_info->frame = 0;
	v4l_info->mmap.frame=v4l_info->frame;

	/* 把/dev/video0 文件映射到内存中 [mmap] */
	v4l_info->map = mmap(0,v4l_info->mbuf.size,PROT_READ|PROT_WRITE,MAP_SHARED,v4l_info->dev,0);  
	if ((int)v4l_info->map<0) printf("camera mmap(mbuf.size : error\n");

	/* 开始截取一帧,帧内容自动存入map指向的地址中(/dev/video0) */
	if (ioctl(v4l_info->dev,VIDIOCMCAPTURE,&v4l_info->mmap)<0) printf("camera VIDIOCMCAPTURE : error\n");
	v4l_info->framestat[v4l_info->frame]=1;
	printf("5.camera INIT :ok  capturing_1st_pic\n");
	return 0;
}







int func_camera_exit(struct video4linux_struct *v4l_info)
{
	close(v4l_info->dev);
	printf("close-Camera~~~\n");
	return 0;
}




int func_camera_loop(struct video4linux_struct *v4l_info)
{
//--------------[wait for complete]-------  			
  			if (ioctl(v4l_info->dev , VIDIOCSYNC , &v4l_info->frame)<0) printf("camera VIDIOCSYNC : error\n");
  			v4l_info->framestat[v4l_info->frame]=0;
//---------------[get the address]--------
  			v4l_info->buffer=(char*)(v4l_info->map+v4l_info->mbuf.offsets[v4l_info->frame]);
  		//	*GUI_bmBits=v4l_info->buffer;	
//------------------[for next]------------ 
			v4l_info->frame=(v4l_info->frame+1)%2;	
			v4l_info->mmap.frame=v4l_info->frame;
			if (ioctl(v4l_info->dev,VIDIOCMCAPTURE,&v4l_info->mmap)<0) printf("camera VIDIOCAMCAPTURE : error\n");
			v4l_info->framestat[v4l_info->frame]=1;	
//-----------------------------------------
			printf("func_camera_loop++ : ok  \n");
			return 0;
}


//================[camera]================
//================[camera]================  		 
  		 
  	
		 
//--------------[write_JPEG_file]----------------
//--------------[write_JPEG_file]--------------------------------------------
//--------------[write_JPEG_file]----------------
GLOBAL(void)
write_JPEG_file (char * filename, int quality)
{
  struct jpeg_compress_struct cinfo;
  struct jpeg_error_mgr jerr;
  /* More stuff */
  FILE * outfile;		/* target file */
  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
  int row_stride;		/* physical row width in image buffer */

  cinfo.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo);

  if ((outfile = fopen(filename, "wb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    exit(1);
  }
  jpeg_stdio_dest(&cinfo, outfile);

  cinfo.image_width = image_width; 	/* image width and height, in pixels */
  cinfo.image_height = image_height;
  cinfo.input_components = 3;		/* # of color components per pixel */
  cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
  jpeg_set_defaults(&cinfo);
  jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
  jpeg_start_compress(&cinfo, TRUE);
  row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */

	while (cinfo.next_scanline < cinfo.image_height) 
	{
    row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
    (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
	}

  jpeg_finish_compress(&cinfo);
  fclose(outfile);
  jpeg_destroy_compress(&cinfo);
}


struct my_error_mgr {
  struct jpeg_error_mgr pub;	/* "public" fields */

  jmp_buf setjmp_buffer;	/* for return to caller */
};

typedef struct my_error_mgr * my_error_ptr;


METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{
  my_error_ptr myerr = (my_error_ptr) cinfo->err;

  (*cinfo->err->output_message) (cinfo);

  longjmp(myerr->setjmp_buffer, 1);
}
 


//--------------[read_JPEG_file]----------------
//--------------[read_JPEG_file]--------------------------------------------
//--------------[read_JPEG_file]----------------
GLOBAL(int)
read_JPEG_file (unsigned char* mem_jpeg_src,unsigned char* fb_mem)
{
	unsigned char *buffer_addr;
	int offset=0;
  struct jpeg_decompress_struct cinfo;
  struct my_error_mgr jerr;
  FILE * infile;		/* source file */
  JSAMPARRAY buffer;		/* Output row buffer */
  int row_stride;		/* physical row width in output buffer */

/*
  if ((infile = fopen(filename, "rb")) == NULL) {
    fprintf(stderr, "can't open %s\n", filename);
    return 0;
  }
*/

	cinfo.err = jpeg_std_error(&jerr.pub);
	jerr.pub.error_exit = my_error_exit;
	if (setjmp(jerr.setjmp_buffer)) 
	{
		jpeg_destroy_decompress(&cinfo);
		fclose(infile);
		return 0;
	}
	jpeg_create_decompress(&cinfo);

	jpeg_stdio_src(&cinfo, mem_jpeg_src);

	printf("warning~~~~~\n");
  (void) jpeg_read_header(&cinfo, TRUE);
	printf("warning~~~~~\n");


  (void) jpeg_start_decompress(&cinfo);

  row_stride = cinfo.output_width * cinfo.output_components;
  buffer = (*cinfo.mem->alloc_sarray)
		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);


	printf("jpeg width: %d\n",cinfo.output_width);
	offset=0; 
	while (cinfo.output_scanline < cinfo.output_height) 
	{
	   (void) jpeg_read_scanlines(&cinfo, buffer, 1);

		buffer_addr=buffer[0];
		RGB24_to_RGB565(buffer_addr,fb_mem+offset,cinfo.output_width); //one line : width
		
		offset+=240*2;

	}

  (void) jpeg_finish_decompress(&cinfo);

  jpeg_destroy_decompress(&cinfo);

  fclose(infile);
  return 1;
}









int main()
{
	struct video4linux_struct v4l_info; 











//	unsigned char *camera_buffer;
//	unsigned char *jpeg_buffer;
	int offset_i,offset_j;
	int i=0,j;
//	char filename[20];
	int tmpb;
	int fb;
//	unsigned char * tmpb_mem;
	unsigned char * fb_mem;

//-------------[frame-buffer&mmap]------------------------------
	fb = open ("/dev/fb0", O_RDWR);
	printf("fb: %d\n",fb);
	if (fb<0) return -1;

	fb_mem = mmap (NULL, 240*360, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);
	printf("fb_mem: %d\n",(int)fb_mem);
	if ((int)fb_mem<0) return -1;



//--------------[camera.jpg&mmap]----------------------------
/*	tmpb = open("/tmp/camera.jpg",O_RDWR);
	printf("outfile: %d\n",tmpb);
	if (tmpb<0) return -1;

	tmpb_mem = mmap (*/



	/* INIT the camera */
	if (func_camera_init(&v4l_info)==-1) { printf("camera INIT: error\n"); return -1; } 
//	jpeg_buffer=malloc(320*240*3);
/*
	while(i>=0)
	{
		fun_camera(2,&camera_buffer);
		image_buffer=camera_buffer;
		image_width=320;
		image_height=240;
		sprintf(filename,"%d.jpg",i);
		printf("%s\n",filename);
		write_JPEG_file(filename,75);
		i=(i+1)%2;
	}
*/	
		offset_i=0;
		offset_j=0;
		func_camera_loop(&v4l_info);
//		read_JPEG_file (camera_buffer,fb_mem);
/*
		printf("fopen\n");
		outfile =fopen ("/tmp/a.jpg","wb");
		if (outfile==NULL)
		{
			printf("open outfile: error\n"); 
			return 0;
		}
		printf("start writing... %x\n",(unsigned int)camera_buffer);
		while (fwrite(camera_buffer+offset_i,1,1,outfile)) offset_i++;
		fclose(outfile);
		printf("write over  %d\n",offset_i);
*/
		for (i=0;i<240;i++)
		{
			for (j=0;j<240*2;j++)
			{
				*(fb_mem+offset_i+j)=*(v4l_info.buffer+offset_j+j);
			}
			offset_i+=240*2;
			offset_j+=320*2;
		}

	func_camera_exit(&v4l_info);	
	close(fb);
	return 0;
}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -