关于嵌入式软件开发的项目电子相册

#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include<stdlib.h>//for malloc
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>    
#include <linux/input.h>  //输入子系统
#include <sys/mman.h>//for mmap
#include <jpeglib.h>
char Cover[]="04.bmp";
char Cover2[]="1.bmp";
char Cover3[]="2.bmp";
char Cover4[]="3.bmp";
int *plcd = NULL;
int x;
typedef char Elemtype;//数据元素的类型
//数据结点
struct node 
{
	Elemtype *data;//指针域
	int time;//时间
	struct node *next,*prev;	//指针域,保存下一个结点的地址和上一个结点的地址
};
//头结点
typedef struct linkedlist
{
	struct node *first;//指向第一个结点
	struct node *last;//指向最后一个结点
	int num;//数据结点个数
}LinkedList;
/*
创建头结点
*/
LinkedList *create_doublelist_head()
{
	LinkedList *l = (LinkedList *)malloc(sizeof(LinkedList));
	
	l->first = NULL;
	l->last = NULL;
	l->num = 0;
	
	return l;
	
}
struct node *print_double_list_display01(struct node *q);
/*
把元素x,加入到头结点指向的链表中
*/
void Add_Elem_To_Double_List(LinkedList *l,Elemtype *x,int TIME)
{
	//创建一个新结点
	struct node *p = (struct node *)malloc(sizeof(struct node));
	
	p->data = x;
	p->next = NULL;
	p->prev = NULL;
	p->time = TIME;
	
	//把结点p加入到链表中
	if(l->first == NULL )//if(l->num == 0)
	{
		l->first = p;
		l->last = p;
		l->num=1;
	}else
	{
		
		struct node *pk = l->first;
		
		while(pk==l->last)
		{
			if(pk->time > p->time)
			{
				break;
			}
			pk=pk->next;
		}
		//2.插入
		if(pk == NULL)
		{
			//尾插法
			l->last->next = p;
			p->prev=l->last;
			l->last = p;
			l->num++;
		}else if(pk == l->first)
		{
			//头插法
			p->next = l->first;
			l->first->prev = p;
			l->first = p;
			l->num++;
		}else
		{
			p->next = pk;
			p->prev = pk->prev;
			pk->prev->next = p;
			pk->prev = p;
			l->num++;
		}
		l->last->next=l->first;
		l->first->prev=l->last;
	}
}
LinkedList *InitializePicture()
{
	LinkedList *lIst = NULL;
	
	lIst = create_doublelist_head();
	DIR *list;	
	
	list = opendir("./");//第0个参数 是我们的指令  ./文件名   参数1  .... 
	if(list == NULL)
	{
		perror("open list failed\n");
	}

	struct dirent *list_name;
	struct stat  buf;
	int i;
	while(1)
	{
		list_name = readdir(list);  //readdir 一次读取一个文件信息
		if(list_name == NULL)
		{
			break;
		}
		int i=findfilebmp(list_name->d_name);
		int j=findfilejpg(list_name->d_name);
		if(i==-1) 
		{
			if(j==-1) 
			{
				continue;
			}else
			{
				i=stat(list_name->d_name,&buf);
				if(i==-1)
					{
						perror("stat");
						return 0;
					}
				Add_Elem_To_Double_List(lIst,list_name->d_name,(int)buf.st_atime);
			}
		}else
		{
			i=stat(list_name->d_name,&buf);
				if(i==-1)
					{
						perror("stat");
						return 0;
					}
				Add_Elem_To_Double_List(lIst,list_name->d_name,(int)buf.st_atime);
		}
		//printf("%s\n",list_name->d_name);
	}
	
	closedir(list);
	return lIst;
}
//判断是否为.bmp文件
int findfilebmp(Elemtype *p)
{
	int i,l=strlen(p);
	if(p[l-1]=='p'&&p[l-2]=='m'&&p[l-3]=='b'&&p[l-4]=='.'&&p[0]=='a')
	{
		return 1;
	}
	return -1;
}
//判断是否为.jpg文件
int findfilejpg(Elemtype *p)
{
	int i,l=strlen(p);
	if(p[l-1]=='g'&&p[l-2]=='p'&&p[l-3]=='j'&&p[l-4]=='.'&&p[0]=='a')
	{
		return 1;
	}
	return -1;
}
//选择打印方式
void select1(Elemtype *p)
{
		int i=findfilebmp(p);
		if(i==-1) 
		{
			display_jpeg(p);
		}else
		{
			lcd_display(p);
		}
}
/*
打印链表中的图片
*/
void print_double_list_display(LinkedList *l)
{
	if(l == NULL)
	{
		return ;
	}
	int times=0;
	struct node *p = l->first;
	while(times<l->num)
	{
		select1(p->data);
		usleep(1000000);
		p=p->next;
		times++;
	}	
}
/*
反序打印链表中的图片
*/
void print_double_list_display1(LinkedList *l)
{
	if(l == NULL)
	{
		return ;
	}
	int times=0;
	struct node *p = l->last;
	while(times<l->num)
	{
		select1(p->data);
		printf("time:%d \n",p->time);
		usleep(1000000);
		p=p->prev;
		times++;
	}
}
//删除一张名字为Elemtype *x的图片
LinkedList *delete_all_x(LinkedList *l,Elemtype *x)
{
	char *r=x;
	struct node *px = l->first;//遍历使用的指针
	struct node *pf = l->first;//指向需要删除的结点的下一个结点,每次继续查找开始的结点
	int T=ts_event(),times=0;
	if(T==1||T==2)
	{
		px = pf;
		while(times<l->num)//寻找要删除的结点
		{
			if(px->data == x)
			{
				break;
			}
			px = px->next;
			times++;
		}
		
		if(px == NULL)
		{
			return NULL;
		}
		pf = px->next;//下一次查找应该从px后面开始
		
		if(px == l->first)
		{
			if(l->first->next == NULL)
			{
				l->first = NULL;
				l->last = NULL;
				l->num--;
				free(px);
				return l;	
			}
			
			l->first = px->next;
			px->next = NULL;
			l->first->prev = l->last;
			l->num--;
			free(px);
		}else if(px == l->last)
		{
			l->last = px->prev;
			l->last->next = l->first;
			px->prev = NULL;
			l->num--;
			free(px);
		}else
		{
			px->prev->next = px->next;
			px->next->prev = px->prev;
			px->next = NULL;
			px->prev = NULL;
			l->num--;
			free(px);
		}
		printf("delete %s success\n",r);
	}else
	{
		printf("delete %s bashing\n",r);
	}
	return l;
}
/*
反序打印链表中的图片
*/
void print_double_list_display11(LinkedList *l)
{
	printf("link:\n");
	if(l == NULL)
	{
		perror("link");
		return ;
	}
	printf("\nl->num=%d\n",l->num);
	int times=0;
	struct node *p = l->last;
	while(times<l->num)
	{
		printf("name:%s \n",p->data);
		p=p->prev;
		times++;
	}
}
/*
功能实现模块手动浏览
*/
void FunctionRealization(LinkedList *l)
{
	struct node *p=l->first;
	struct node *q=l->last;
	struct node *pre=NULL;
	LinkedList *s=NULL;
	int x,i=0;
	print_double_list_display11(l);
	while(1)
	{
		x=ts_event();
		switch(x)
		{
			case 1:
				{
					p=p->next;
					select1(p->data);
					printf("  display:%s\n",p->data);					
					continue;
				}
			case 2:
				{
					p=p->prev;
					select1(p->data);
					continue;
				}
		}
		if(x==4)
		{
			pre=p;
			s=delete_all_x(l,p->data);
			print_double_list_display11(s);
			p=s->first;
			q=s->last;
		}
		if(x==3)
		{
			break;
		}
	}

}
/*
一.实现在lcd屏幕上显示一张图片
1.打开bmp文件 和 lcd屏幕文件
2.读取bmp文件的像素点信息
3.数据转换
4.把信息写入我们lcd屏幕上
5.关闭文见
*/
int lcd_display(Elemtype *file)
{
	//1.打开bmp文件 和 lcd屏幕文件
	int lcd_fd;
	printf("%s\n",file);
	lcd_fd = open("/dev/fb0",O_RDWR);
	if(lcd_fd < 0)
	{
		perror("lcd failed");
	}
	FILE *fp;
	puts(file);
	fp=fopen(file,"r");
	if(fp == NULL)
	{
		perror("open bmp failed");
		return -1;
	}
	
	//跳过文件头部属性信息 54 个字节  1152054-54=1152000 全部都是像素点信息
	fseek(fp,54,SEEK_SET);
	
	char bmp_buf[800*480*3];
	int  lcd_buf[800*480];
	//2.读取bmp文件的像素点信息
	int ret;
	
	ret=fread(bmp_buf,800*480,3,fp);
	if(ret<3)
	{
		perror("read failed\n");
	}
	
	int  *p;
	p=mmap(NULL,800*480*4, PROT_READ |PROT_WRITE, MAP_SHARED,lcd_fd,0);
	
	//3字节数 转换为4字节
	int i,j;
	for(i=0,j=0;i<800*480;i++,j=j+3)
	{	//             b    |  g <<8   |r <<16  |0 <<24
		lcd_buf[i]= bmp_buf[j] | bmp_buf[j+1] << 8   | bmp_buf[j+2] << 16 | 0 << 24 ;
	}
	
	int show_bmp[480*800];
	//数据反转
	int x,y;
	for(y=0;y<480;y++)
	{
		for(x=0;x<800;x++)
		{
			show_bmp[x+800*(479-y)]=lcd_buf[x+800*y];
		}
	}
	//将图片放入映射
	for(i=0;i<800*480;i++)
	{	
		*(p+i)=show_bmp[i];
	}
	int k;
		for(k=0;k<60;k++)
		{
			for(i=k;i<480;i+=60)
			{
				for(j=0;j<800;j++)
				{
					*(p+800*i+j)=lcd_buf[j+800*(479-i)];
				}
			}
		}	
	munmap(p,800*480*4);
	close(lcd_fd);
	fclose(fp);
	return 0;
}
int display_jpeg( char *jpegfile)
{
	int lcd_fd;
	printf("%s\n",jpegfile);
	lcd_fd = open("/dev/fb0",O_RDWR);
	if(lcd_fd < 0)
	{
		perror("lcd failed");
	}
	FILE *fp;	
	struct jpeg_decompress_struct dinfo; //声明一个解压的对象
	struct jpeg_error_mgr jerr; //声明一个出错信息的对象
	int width, height, components;
	int x, y;
	unsigned char a, r, g, b;
	int color;
			
	jpeg_create_decompress(&dinfo); //初始化dinfo这个解压对象
	dinfo.err = jpeg_std_error(&jerr); //初始化这个出错对象
	fp = fopen( jpegfile, "r" );
	if( NULL == fp)
	{
		perror(" open jpeg file");
		return 1;
	}
	//指定要解压的图像文件
	jpeg_stdio_src(&dinfo, fp);
	
	//获取图像头信息
	jpeg_read_header(&dinfo, TRUE);

	//启动解压过程
	jpeg_start_decompress(&dinfo);
	
	width = dinfo.output_width;
	height = dinfo.output_height;
	components = dinfo.output_components;
	printf(" jpeg : width = %d, height = %d, components = %d\n", width, height, components);
	//申请一个能存储一行像素的颜色信息的空间
	unsigned char *pixel = ( unsigned char *) malloc(  width*components );
	plcd=mmap(NULL,800*480*4, PROT_READ |PROT_WRITE, MAP_SHARED,lcd_fd,0);
	//dinfo.output_scanline表示已经扫描了多少行,以0开始	
	while( dinfo.output_scanline < height ) 
	{
		y = dinfo.output_scanline;
		//下面函数结束后,pixel里头就有一行颜色数据
		jpeg_read_scanlines(&dinfo,  //解压对象
					            &pixel,//保存解压后数据的二级指针	
						    1 //读取多少行数据来解压
						    );	
		unsigned char *p = pixel;
		for( x=0; x<width; x++ )
		{
			if ( 4 == components)
				a = *p++;
			else
				a = 0x0;
			r = *p++;
			g = *p++;
			b = *p++;
			//color必须根据lcd的颜色格式来组装
			color = ( a<<24 ) | (r<<16) | (g<<8) | b;
			*(plcd + 800*y + x) = color;		
		}		
	}
	//完成解压过程
	jpeg_finish_decompress( &dinfo);
	//释放jpeg解压对象dinfo
	jpeg_destroy_decompress	(&dinfo);
	munmap(plcd,800*480*4);
	free(pixel);
	fclose(fp);
}
/*
//目的是 获取触摸屏的值
第一步:打开触摸屏设备文件

第二步:定义一个结构体存储触摸屏信息

第三步:读取触摸屏信息

第四步:打印出触摸屏信息
*/
int ts_event()
{
	int fdts,i;
	int x1=-1,y1=-1,x2=-1,y2=-1;
	int ret=0;
	struct input_event ts;
	x=0;
	fdts = open("/dev/input/event0",O_RDONLY);
	if(fdts < 0)
	{
		perror("ts open fail");
		return -1;
	}


	while(1)
	{
		//读触摸屏,当有按下事件产生之后,在去读两次,触摸屏,如果只读一次,可能只能读到y的坐标,读到之后作为初始的坐标值
		read(fdts,&ts,sizeof(struct input_event));
		if(ts.type == EV_KEY && ts.code == 0x14a && ts.value == 1) //有触摸屏按下
		{
		//这里需要多读几次才能读到y轴的坐标
			for(i=0;i<3;i++)
			{
				read(fdts,&ts,sizeof(struct input_event));
				if(ts.type == EV_ABS)
				{

					if(ts.code == ABS_X)
					{
						x1=ts.value;
				//		printf("1 x1 =%d\n",x1);
					}
					else if(ts.code == ABS_Y)
					{
						y1=ts.value;
			//			printf("1 y1=%d\n",y1);
					}
				}
			}
		//	printf("x1=%d y1=%d\n",x1,y1);
		}
		//在这里一直不断读取x y的坐标,保存到x2,y2变量当中
		if(ts.type == EV_ABS)
		{
			if(ts.code == ABS_X)
			{
				x2=ts.value;
			}
			else if(ts.code == ABS_Y)
			{
				y2=ts.value;
			}
		}
		//当有弹起状态的时候,退出循环,并且得到最新的x,y的坐标
		if(ts.type == EV_KEY && ts.code == 0x14a && ts.value == 0) //受离开触摸屏
		{
		//	printf("x2=%d y2=%d\n",x2,y2);
			close(fdts);
			break;
		}
	}
	if(y1-y2>10&&(abs(x1-x2)<abs(y1-y2)))
	{
		ret =3;
		//printf("shang\n");
	}
	else if(y2-y1>10&&(abs(x1-x2)<abs(y1-y2)))
	{
		ret =4;
		//printf("shang\n");
	}
	else if(((x2-x1)>20)&&((abs(x1-x2))>(abs(y1-y2))))
	{
		ret =1;
		//printf("you\n");
	}
	else if(((x1-x2)>1)&&((abs(x1-x2))>(abs(y1-y2))))
	{
		ret =2;
		//printf("zuo\n");
	}
	printf("\nret=%d\n",ret);
	return ret;
}
/*
功能实现模块自动浏览
*/
void FunctionRealization1(LinkedList *l)
{
	int x;
	while(1)
	{
		x=ts_event();
		switch(x)
		{
			case 1:
			{
				print_double_list_display(l);
				lcd_display(Cover2);
				continue;
			}
			case 2:
			{
				print_double_list_display1(l);
				lcd_display(Cover2);
				continue;
			}
			case 3:
			{
				return;
			}
		}
	}
}
//主函数
int main()
{
	LinkedList *list = NULL;
	list = create_doublelist_head();
	list = InitializePicture();
	
	lcd_display(Cover);
	usleep(600000);

	while(1)
	{
		lcd_display(Cover4);
		x=ts_event();
		if(x==1)
		{
			lcd_display(Cover3);
			FunctionRealization(list);
		}
		if(x==2)
		{
			lcd_display(Cover2);
			FunctionRealization1(list);
		}
		if(x==3)
		{
			lcd_display(Cover);
			break;
		}
	}
	free(list);
	return 0;
}
  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值