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

mac2022-07-05  35

#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; }
最新回复(0)