#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <linux/input.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
struct list_node{
char picname[20];
struct list_node *next;
struct list_node *prev;
};
struct list_node *init_list_head()
{
//1. 為頭節點申請空間。
struct list_node *head = malloc(sizeof(struct list_node));
//2. 為頭節點指派。
head->next = NULL;
head->prev = NULL;
return head;
}
void insert_picname_to_list(struct list_node *head,char *picname)
{
//1. 為新節點指派。
struct list_node *new = malloc(sizeof(struct list_node));
//2. 為資料域與指針域指派。
strcpy(new->picname,picname);
new->next = NULL;
//3. 尋找最後一個節點
struct list_node *p = NULL;
for(p=head;p->next!=NULL;p=p->next);
//4. 處理指針關系。
p->next = new;
new->prev = p;
return;
}
void show_list_node(struct list_node *head)
{
struct list_node *p = NULL;
for(p=head->next;p!=NULL;p=p->next)
{
printf("p->picname:%s\n",p->picname);
}
return;
}
void mmap_show_bmp(const char *picname)
{
char bmp_buf[800*480*3] = {0}; //圖檔每一個像素點都是由3個位元組組成,是以一共有800*480*3個位元組。
char lcd_buf[800*480*4] = {0}; //lcd每一個像素點都是由4個位元組組成,是以一共有800*480*4個位元組。
char show_buf[800*480*4] = {0};
int x,y;
int i,j,k;
//1. 通路圖檔檔案。
FILE *fp = fopen(picname,"r"); //目前的光标在最開頭
if(fp == NULL)
printf("fopen error!\n");
//2. 通路lcd液晶裝置
int lcd = open("/dev/fb0",O_RDWR);
if(lcd < 0)
printf("open lcd error!\n");
//3. 跳過54個頭資料。
fseek(fp,54,SEEK_SET);
//4. 将圖檔的資料讀取到一個緩沖區中。
int n = fread(bmp_buf,800*480*3,1,fp);
if(n != 1)
printf("fread error!\n");
//5. 24位轉32位
for(i=0,j=0;i<800*480*4;i+=4,j+=3)
{
lcd_buf[i] = bmp_buf[j];
lcd_buf[i+1] = bmp_buf[j+1];
lcd_buf[i+2] = bmp_buf[j+2];
lcd_buf[i+3] = 0;
}
//6. 上下颠倒
for(y=0;y<480;y++)
{
for(x=0;x<800*4;x++)
{
show_buf[800*4*(479-y)+x] = lcd_buf[800*4*y+x];
}
}
//7. 記憶體映射
char *p = mmap(NULL,800*480*4,PROT_WRITE|PROT_READ,MAP_SHARED,lcd,0);
if(p == (void *)-1)
printf("mmap error!\n");
//8. 不斷将show_buf的内容拷貝到記憶體空間。
for(k=0;k<800*480*4;k++)
{
memcpy(p+k,&show_buf[k],1);
}
//9. 撤銷映射
munmap(p,800*480*4);
//10.關閉檔案。
close(lcd);
fclose(fp);
return;
}
int delete_list_node(struct list_node *head,char *del_picname)
{
struct list_node *p = NULL;
struct list_node *q = NULL;
for(q=head,p=head->next;p!=NULL;q=p,p=p->next)
{
if(strcmp(p->picname,del_picname) == 0)
{
q->next = p->next;
if(p->next!=NULL)
p->next->prev = q;
free(p);
return 0;
}
}
return -1;
}
int main(int argc,char *argv[])
{
//1. 初始化連結清單頭
struct list_node *head = NULL;
head = init_list_head();
//2. 打開目錄。
DIR *dp = opendir("./bmp_data");
if(dp == NULL)
printf("opendir error!\n");
//3. 切換目錄。
chdir("./bmp_data");
//4. 不斷讀取目錄。
struct dirent *ep = NULL;
while(1)
{
ep = readdir(dp);
if(ep == NULL)
break;
if(ep->d_name[0] == '.')
continue;
insert_picname_to_list(head,ep->d_name);
}
//5. 周遊連結清單。
//show_list_node(head);
//5. 顯示第一張圖檔。
struct list_node *p = head->next;
mmap_show_bmp(p->picname);
//5.5 找到最後一張的指針。
struct list_node *tmp = NULL;
struct list_node *last;
//6. 進入觸摸屏狀态。
int ts = open("/dev/input/event0",O_RDWR);
//7. 讀取觸摸屏的資料。
struct input_event buf;
int x,y;
while(1)
{
read(ts,&buf,sizeof(buf));
if(buf.type == 3 && buf.code == 0)
{
x = buf.value;
}
if(buf.type == 3 && buf.code == 1)
{
y = buf.value;
}
if(buf.type == 1 && buf.code == 330 && buf.value == 0)
{
for(last=head;last->next!=NULL;last=last->next);
if(x < 300) //上一張
{
if(p->prev == head) //說明目前正在顯示第一張
{
p = last;
}
else{
p = p->prev;
}
mmap_show_bmp(p->picname);
}
if(x > 724) //下一張
{
if(p->next == NULL)
{
p = head->next;
}
else{
p = p->next;
}
mmap_show_bmp(p->picname);
}
if(x > 300 && x < 724 && y > 300)
{
break;
}
if(x > 300 && x < 724 && y < 300)
{
tmp = p->next;
if(tmp == NULL)
{
tmp = head->next;
}
mmap_show_bmp(tmp->picname);
delete_list_node(head,p->picname);
p = tmp;
}
}
}
return 0;
}