#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
//必须添加该头文件
#include <linux/input.h>
int lcd_fd=0;
int ts_fd =0;
unsigned int *FB=NULL;
struct node
{
char data[1024]; //数据域
struct node *next; //后驱指针,保存后面节点的地址
struct node *prev; //前驱指针,保存前面节点的地址
};
//头插
void add_last(struct node *head,char *str)
{
//1.创建新节点
struct node *new = malloc(sizeof(struct node));
new->next = NULL;
new->prev = NULL; //循环起来了
strcpy(new->data,str);
//2.插入节点
head->prev->next = new;
new->prev = head->prev;
head->prev = new;
new->next = head;
}
//删除链表中的节点
void del_node(struct node*head,char *str)
{
//指向头节点
struct node *pos = head->next;
//查找需要删除的节点
while(pos!= head)
{
if(strcmp(pos->data,str) == 0) //找到需要删除的数据
{
//删除节点
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
//把需要删除的节点完全与链表脱离关系
struct node *tmp = pos;
pos = pos->prev; //回退
tmp->next = NULL;
tmp->prev = NULL;
free(tmp);
}
pos = pos->next;
}
return ;
}
//获取文件大小
int get_file_size(char *file_path)
{
int fd = open(file_path,O_RDWR);
if(fd < 0)
{
// perror("");
return 0;
}
int size=lseek(fd,0,SEEK_END);
close(fd);
return size;
}
//检索系统中的 bmp 文件
int read_pic(char *dir_path,struct node *head)
{
//读取目录中的图片
DIR *dp = opendir(dir_path);
if(dp==NULL)
{
return -1;
}
//读取目录中的文件名
while(1)
{
struct dirent *msg=readdir(dp);
if(msg == NULL)
{
break;
}
//判断名字
if(msg->d_name[0] == '.')
{
continue; //跳过隐藏文件
}
//判断是否为目录是的话就继续读取
if(msg->d_type == DT_DIR) //目录
{
//拼接路径
char path[2096]={0};
sprintf(path,"%s/%s",dir_path,msg->d_name);
//递归调用
read_pic(path,head);
}
if(msg->d_type == DT_REG) //普通文件
{
if(strstr(msg->d_name,".bmp") )
{
//拼接为绝对路径
char path[2096]={0};
sprintf(path,"%s/%s",dir_path,msg->d_name);
//把处理后的图片挂载到链表中
add_last(head,path);
}
}
}
//关闭目录
closedir(dp);
}
//初始化LCD
int init_lcd_ts()
{
//打开LCD设备文件
lcd_fd = open("/dev/fb0", O_RDWR);
if(lcd_fd == -1)
{
perror("lcd open failed");
return 0;
}
//FB指向的就是每个aRGB像素
FB = mmap(NULL, 4*800*480, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd,0);
if(FB == MAP_FAILED)
{
perror("mmap failed");
return 0;
}
//1.打开触摸屏设备文件
ts_fd=open("/dev/input/event0",O_RDWR);
if(ts_fd < 0)
{
perror("");
return -1;
}
}
//释放LCD TS
void free_lcd()
{
close(lcd_fd);
munmap(FB,4*800*480);
close(ts_fd);
}
//图片处理
int show_bmp(char *pic)
{
//1.打开BMP 图像
//printf("测试:%s\n",pic);
int bmp = open(pic,O_RDWR);
if(bmp < 0 )
{
perror("");
return -1;
}
//2.读取BMP图片的头信息
unsigned char head[54];
read(bmp,head,54);
//3.获取长度与宽度
//head[18] , head[19] , head[20] , head[21] //表示图像的宽度
unsigned int kuan = head[18] | head[19] << 8 | head[20] << 16 | head[21]<<24;
unsigned int gao = head[22] | head[23] << 8 | head[24] << 16 | head[25]<<24;
printf("宽=%d,高=%d\n",kuan,gao);
//1.根据宽和高 处理图像 转换成 32 位图
unsigned char buf[kuan*gao*3];
read(bmp,buf,sizeof(buf));
unsigned char *p = buf;
int color[kuan*gao];
int i;
for( i=0;i<kuan*gao;i++)
{
unsigned char b = *p++; //b
unsigned char g = *p++;//g
unsigned char r = *p++;//r
unsigned char a = 0;
color[i] = a << 24 | r << 16 | g << 8 | b; //得到一个32位色
};
//2.把处理后 的图像显示到 LCD 设备中
unsigned int *lcd = FB;
//判断宽和高
if(kuan < 800 && gao < 480)
{
//求中间点
int x = (800 - kuan)/2;
int y = (480 - gao) /2;
//LCD偏移到中间点
lcd = lcd + x + y*800;
}
int x, y;
for(y=0; y<gao; y++)
{
for(x=0; x<kuan; x++)
{
if(x < 800 && y < 480) //防止图像超出LCD最大的显示范围
{
*(lcd + x +y*800) = color[x+kuan*(gao-1-y)]; //赋值一行数据
}
}
}
// 5.关闭 //关闭bmp文件描述符
close(bmp);
//printf("--------1------");
}
//返回 1 2 3 4 //确定点击的位置
int get_xy()
{
//2.读取输入事件到 输入模型中
int x=0,y=0;
int p = 0;
while(1)
{
struct input_event ts;
read(ts_fd,&ts,sizeof(ts));
//3.利用事件值处理获取到的坐标点
if(ts.type == EV_ABS && ts.code == ABS_X) //X轴的坐标点
{
x = ((ts.value*800)/1024);
p = 0;
}
if(ts.type == EV_ABS && ts.code == ABS_Y) //Y轴的坐标点
{
y = ((ts.value*480)/600);
p = 1;
}
//打开X Y 坐标的
if(x> 0 && y > 0)
if(p == 1)
{
printf("x=%d,y=%d\n",x,y);
if((x > 300 && x < 490) &&(y > 180 && y < 300) )
{
return 1; //加载
}
else if((x > 80 && x < 200) &&(y > 380 && y < 480) )
{
return 2; //自动
}
else if((x > 290 && x < 450) && (y > 380 && y < 480))
{
return 3; //手动
}
else if((x > 0 && x < 100)&&(y > 0 && y < 480))
{
return 4; //退出
}
x = 0;
y = 0;
}
}
}
//手动播放
int ctrl_play()
{
//show_bmp("pick.bmp");
//2.读取输入事件到 输入模型中
int x=0,y=0;
int p = 0;
while(1)
{
struct input_event ts;
read(ts_fd,&ts,sizeof(ts));
//3.利用事件值处理获取到的坐标点
if(ts.type == EV_ABS && ts.code == ABS_X) //X轴的坐标点
{
x = ((ts.value*800)/1024);
p =0;
}
if(ts.type == EV_ABS && ts.code == ABS_Y) //Y轴的坐标点
{
y = ((ts.value*480)/600);
p =1;
}
//打开X Y 坐标的
if(x> 0 && y > 0)
if(p == 1)
{
printf("x=%d,y=%d\n",x,y);
//删除按钮
if(x > 200 && x < 400 && y > 330 && y < 480)
{
return 3; //退出
}
if(x > 0 && x < 400 && y > 100 && y < 300)
{
return 1; //上一张
}
else if(x > 400 && x < 800 && y > 100 && y < 300 )
{
return 2; //下一张
}
}
}
}
//清屏
void clean_lcd()
{
int i;
for( i=0;i<800*480;i++)
{
*(FB+i) = 0xffffff;
}
}
void show(struct node *head)
{
struct node *pos = head->next; //指向第一个节点
while(pos != head) //因为当 pos == head 的时候该循环链表 已经跑了一遍
{
printf("%s\n",pos->data);
if(strstr(pos->data,".bmp"))
{
//显示bmp
clean_lcd();
show_bmp(pos->data);
}
pos = pos->next;
sleep(1);
}
}
//手动播放
void play( struct node *head)
{
struct node *pos = head->next;
//显示bmp
clean_lcd();
show_bmp(pos->data);
while(1)
{
int b = ctrl_play();
switch(b)
{
case 1:
{
pos = pos->prev;
if(strstr(pos->data,".bmp"))
{
show_bmp(pos->data);
}
sleep(1);
break;
}
case 2:
{
pos = pos->next;
if(strstr(pos->data,".bmp"))
{
show_bmp(pos->data);
}
break;
}
case 3:
{
return ;
break;
}
default :
printf("你的输入有误\n");
break
}
}
}
int main(int argc,char *argv[])
{
//创建一个链表的头节点
struct node *head = malloc(sizeof(struct node));
head->next = head;
head->prev = head; //循环起来了
bzero(head->data,1024);
//初始化LCD
init_lcd_ts();
//读取用户输入的目录
read_pic(argv[1],head);
//显示主界面
show_bmp("pick.bmp");
while(1)
{
//获取点击的坐标位置
int a = get_xy();
switch(a)
{
case 1:
{
printf("加载图片\n");
read_pic(argv[1],head);
printf("加载完毕!!!\n");
break;
}
case 2:
{
printf("自动播放\n");
show(head);
show_bmp("pick.bmp");
printf("自动播放完毕");
break;
}
case 3:
{
printf("手动浏览\n");
play(head);
show_bmp("pick.bmp");
printf("手动结束\n");
break;
}
case 4:
{
printf("退出程序\n");
break;
}
}
}
show(head);
return 0;
}