#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;
}
关于嵌入式软件开发的项目电子相册
最新推荐文章于 2024-04-05 16:49:42 发布