数码相册项目

一、设计目标:

        开发一个类似相册的应用程序,利用开发板的液晶屏和触摸屏,支持用户友好界面、多种图片格式,并提供方便浏览照片的功能。

二、功能描述:

  1. 支持滑动浏览图片:用户可以通过触摸屏滑动操作,在指定目录下浏览图片。

  2. 支持幻灯片播放:提供幻灯片播放功能,用户可以选择自动播放图片。

  3. 解析图片格式:应用程序智能调用相关的库,对支持的图片格式(如JPG和BMP)进行解析显示。

  4. 目录文件过滤:应用程序支持指定目录下的文件过滤,以获取所有符合条件的图片文件。

  5. 图片自动居中:应用程序会自动将图片在屏幕上居中显示,确保用户可以完整地看到图片内容。

  6. 图片自适应屏幕尺寸:应用程序会自动缩放大图,以适应屏幕尺寸,保证图片显示效果。

  7. 双缓冲机制:为了优化画面显示效果,应用程序采用双缓冲机制,避免闪屏现象。

  8. 功能选择:提供一个功能选择页面,用户可以选择浏览照片、幻灯片播放或其他功能。

三、设计方案:

  1. 硬件方面:使用开发板的液晶屏和触摸屏来显示图片,并支持滑动操作。

  2. 数据结构:采用内核双向链表来保存目录下的文件信息,包括文件名、路径等。通过遍历链表来实现图片的显示和滑动操作。

  3. 用户界面设计:设计一个用户友好的界面,通过触摸屏进行交互操作。

  4. 功能实现:根据用户操作,调用相应的功能模块,如图片显示模块、幻灯片播放模块等。

  5. 动态库加载:根据图片格式,动态加载相应的库进行解析和显示。

  6. 目录检索和文件过滤:使用文件系统相关的API,遍历指定目录,筛选出符合条件的图片文件。

四、系统框架

  1. 用户界面层:
    1. 主页:显示电子相册的主界面,提供功能选择入口。
    2. 浏览界面:展示图片,支持滑动操作和幻灯片播放。
  2. 应用逻辑层:
    1. 图片管理模块:负责管理图片数据和文件信息,包括读取目录、文件过滤、链表存储等。
    2. 图片显示模块:负责显示图片,支持居中和自适应屏幕尺寸。
    3. 幻灯片播放模块:实现幻灯片自动播放功能,包括时间间隔控制和图片切换。
    4. 功能选择模块:处理用户选择的功能,根据不同选项调用相应模块。
  3. 库调用层:
    1. 图片解析库:根据图片格式动态加载相应的库文件,解析并显示图片。
    2. 文件系统库:提供文件操作接口,用于目录遍历和文件过滤。
  4. 硬件驱动层:
    1. LCD驱动:控制液晶屏的显示。
    2. 触摸屏驱动:处理用户触摸输入。
  5. 系统核心层:
    1. 操作系统:提供系统资源管理和任务调度功能。
    2. 设备驱动:与硬件驱动层配合,实现对硬件设备的操作。

五、实现过程

  1. 初始化lcd
    void lcd_init(struct lcd_info *p)
    {
        p->lcd = open("/dev/fb0",O_RDWR);
        if(p->lcd == -1)
        {
            perror("打开lcd失败");
            return;
        }
    
        // 准备好lcd设备(如果多次显示,应该只做一遍)
        static bool initialized = false;
        if(initialized)
        {
            return;
        }
    
        // 获取硬件参数
        ioctl(p->lcd,FBIOGET_VSCREENINFO,&finfo);
    
        p->width = finfo.xres;
        p->height = finfo.yres;
        p->bpp = finfo.bits_per_pixel;
        p->screen_size = p->width * p->height * p->bpp/8;
    
        // 映射内存
        p->fmb = mmap(NULL,p->screen_size*2,PROT_READ|PROT_WRITE,MAP_SHARED,p->lcd,0);
        if(p->fmb == MAP_FAILED)
        {
            perror("内存映射失败");
            exit(0);
        }
    
        //将映射的内存块清零
        bzero(p->fmb,p->screen_size);
        initialized = true;
    }

  2.  初始化内核链表
    struct photo *init_list()
    {
        struct photo *head = calloc(1, sizeof(struct photo));
        if(head != NULL)
        {
            INIT_LIST_HEAD(&head->list);
        }
        return head;
    }

  3.  对目录进行操作文件过滤
        // 打开目录获得目录指针
        DIR *dp = opendir(argv[1]);
        if(argc != 2)
        {
            fprintf(stderr,"请指定一个目录\n");
            exit(0);
        }
    
        // 获得当前进程所在路径
        char path[100];
        bzero(path,100);
        printf("当前路径: %s\n",getcwd(path,100));
    
        // 进入目录
        chdir(dirent_path);
    
        // 目录项结构体
        struct dirent *ep;
    
        while (1)
        {
            // 读取目录项
            ep = readdir(dp);
            
            if(ep == NULL)
            {
                printf("读完了\n");
                break;
            }
    
            // 跳过以‘.’开头的文件
            if(ep->d_name[0] == '.')
                continue;
            
            // 过滤不是.jpg格式的文件名
            // DT_REG是普通文件类型
            if (ep->d_type == DT_REG && ((strstr(ep->d_name, ".jpg") !=NULL) || (strstr(ep->d_name, ".bmp")!= NULL)))
            {
                struct photo *p = new_node(ep->d_name);
                list_add_tail(&p->list,&head->list);
            }   
        }

  4.  读取触摸屏数据并判定滑动方向
        int fd = open("/dev/input/event0",O_RDWR);
        if(fd == 0)
        {
            perror("打开触摸屏失败\n");
            return -1;
        }
        struct input_event ev;
    
        int ret;
        int flag = 0;
        int count = 0;
        while(1)
        {
            // 读取触摸屏数据
            ret = read(fd,&ev,sizeof(ev));
            if(ret != sizeof(ev))
            {
                close(fd);
                perror("读取失败");
                return -1;
            }
    
            // 判断触摸事件,并获取x值
            if(ev.type == EV_ABS && ev.code == ABS_X)
            {
                if(p1.x < 0)
                {
                    p1.x = ev.value;
                }
                else
                {
                    p2.x = ev.value;
                }
            }
            if(ev.type == EV_ABS && ev.code == ABS_Y)
            {
                if(p1.y < 0)
                {
                    p1.y = ev.value;
                }
                else
                {
                    p2.y = ev.value;
                }
            }
    
            // 最后读取到的数据与第一次读取到的数据相比较
            // 判断滑动的方向
            if(ev.type == EV_KEY && ev.code == BTN_TOUCH && ev.value == 0)
            {
                int dt_x = abs(p1.x - p2.x);
                int dt_y = abs(p1.y - p2.y);
    
                if(dt_x > 2*dt_y)
                {
                    if(p1.x > p2.x)
                        return left;
                    if(p1.x < p2.x)
                        return right;
                }else if(2*dt_x < dt_y)
                {
                    if(p1.y > p2.y)
                        return up;
                    if(p1.y < p2.y)
                        return down;
                }
                else    // 单击不滑屏
                {
                    p1.x = -1;
                    p1.y = -1;
                    p2.x = -1;
                    p2.y = -1;
                }
            }
            
        }

  5.  根据图片文件名字选择加载哪个类型的动态库
            p = list_entry(pos,struct photo,list);
            //打开指定的动态库,并找到显示图片的函数指针
            void *handle;
            if(strstr(p->name,".jpg"))
            {
                handle = dlopen("libjpg.so",RTLD_NOW);
                printf("%d\n",__LINE__);
            }
            else if(strstr(p->name,".bmp"))
            {
                handle = dlopen("libbmp.so",RTLD_NOW);
                printf("%d\n",__LINE__);
            }
            if(handle == NULL)
            {
                fprintf(stderr,"打开动态库失败:%s\n",dlerror());
                exit(0);
            }
    
            void (*show_img)(const char *jpgFile, struct lcd_info *p);
            show_img = dlsym(handle,"show_img");
            if(show_img == NULL)
            {
                fprintf(stderr,"dlsym()失败:%s\n",dlerror());
                exit(0);
            }

  6.  对滑动后做出响应,显示相应的图片
    switch(x)
            {
                case left:
                    
                    if(pos->prev != &head->list)
                    {
                        pos = pos->prev;
                        printf("向左滑动,前一张\n");
                    }
                    else
                    {
                        printf("最后一张啦,从头开始滑\n");
                        pos = head->list.prev;
                    }
                    break;
                    
                case right:
                    if(pos->next != &head->list)
                    {
                        printf("向右滑动,下一张\n");
                        pos = pos->next;
                    }
                    else
                    {
                        printf("滑到头啦,重新开始\n");
                        pos = head->list.next;
                    }
                    break;
            }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值