粤嵌Linux GEC6818开发板实现电子相册

您所在的位置:网站首页 播放t图片 粤嵌Linux GEC6818开发板实现电子相册

粤嵌Linux GEC6818开发板实现电子相册

2024-01-12 19:40| 来源: 网络整理| 查看: 265

前言

最近学校要求使用粤嵌的开发板实现电子相册,具体的功能要有点击特定的区域实现上一张、下一张、自动播放图片、黑屏退出应用程序、左右滑动切换图片相关功能。其中涉及到的知识点也比较多(文件IO、内存映射、触摸屏、bmp图片格式、进程、线程创建和同步、字符串操作等)。为理清思路和复习去年学的Linux C应用编程知识,特写下此文进行回顾和总结。

先看看效果

粤嵌Linux GEC6818开发板实现电子相册

整个工程文件和使用到的图片在下方链接

门牙会稍息 / 粤嵌GEC 6818开发板实现简易电子相册和音乐播放器 · GitCode

一:内存映射

存储映射 I/O(memory-mapped I/O)是一种基于内存区域的高级 I/O 操作,它能将一个文件映射到进程地址空间中的一块内存区域中,当从这段内存中读数据时,就相当于读文件中的数据(对文件进行 read 操作),将数据写入这段内存时,则相当于将数据直接写入文件中(对文件进行 write 操作)。用到的两个函数是mmap和munmap,函数原型如下:

简言之addr设置为NULL的话内核会自动找一内存空间,大小就是length,粤嵌的屏是800*480的,所以length就是800*480*4,4代表一个像素点由四字节构成(ARGB),port参数设为PROT_READ、PROT_WRITE就是可读可写,flags描述的是映射区的属性。

 二:BMP格式图片

 用hexdump查看一下bmp图片的数据(高度和宽度)

LCD屏显示BMP格式图片的函数

/** *lcd屏显示bmp格式图片函数 *@param pathname 图片名字 *@param x0 图片在LCD上显示的x起点坐标 *@param y0 图片在LCD上显示的y起点坐标 *@return 函数返回值 */ int lcd_show_bmp(char *pathname, int x0, int y0) { //1、打开设备文件 int lcd = open("/dev/fb0", O_RDWR); if(-1 == lcd) { printf("lcd open error!\n"); return -2; } //2、内存映射 char *ptr = (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd, 0); if(NULL == ptr) { printf("mmap error!\n"); return -3; } //清除背景色 //bzero(ptr, 800*480*4); //打开图片 int bmp = open(pathname, O_RDWR); if(-1 == bmp) { printf("bmp open error!\n"); return -2; } //读取图片相关信息 int bmp_size, bmp_width, bmp_height; //大小 lseek(bmp, 2, SEEK_SET); read(bmp, &bmp_size, sizeof(bmp_size)); //宽度和高度 lseek(bmp, 18, SEEK_SET); read(bmp, &bmp_width, sizeof(bmp_width)); read(bmp, &bmp_height, sizeof(bmp_height)); //读取图片的颜色数据 lseek(bmp, 54, SEEK_SET); char *bmp_buf = malloc(bmp_size); //申请空间 read(bmp, bmp_buf, bmp_width*bmp_height*3); //对颜色数据进行处理(上下颠倒以及数据混乱) int bmp_sum = 0; int lcd_sum = 0; for(int y=0; y+y0 150) && (old_x < 600))) { right_left_slide_flag = 1; slider_left = 1; old_x = 300; } } } } //4、关闭文件 close(touch_fd); } 四:创建线程,处理触摸屏坐标数据

阻塞式 I/O 的优点在于能够提升 CPU 的处理效率,当自身条件不满足时,进入阻塞状态,交出 CPU资源,将 CPU 资源让给别人使用;而非阻塞式则是抓紧利用 CPU 资源,譬如不断地去轮训,这样就会导致该程序占用了非常高的 CPU 使用率!我这里是想获得触摸点坐标之后再做相关的操作,当没有按下触摸屏的时候,相关线程就会阻塞挂起,节约资源,线程同步中使用互斥锁和条件变量就可以实现。

左右滑动线程处理函数:

void *right_left_slide_func(void *arg) { printf("enter right_left_slide_func\r\n"); while(1){ if(right_left_slide_flag == 1){ if(slider_left == 1){ touch_flag--; if(touch_flag BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); slider_right = 0; right_left_slide_flag == 0; } right_left_slide_flag == 0; } } }

右侧选项框线程处理函数:

void *area_switch(void *arg) { printf("enter area_switch\r\n"); while(1){ pthread_mutex_lock(&mutex); while(flag_x_y == 0) pthread_cond_wait(&cond, &mutex); while(flag_x_y == 1){ //上一张 if((ts_y > 0 && ts_y < 120) && (ts_x > 600)) { touch_flag--; if(touch_flag 120 && ts_y < 240) && (ts_x > 600)) { touch_flag++; if(touch_flag > BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); ts_x = 0; ts_y = 0; } //幻灯片 else if((ts_y > 240 && ts_y < 360) && (ts_x > 600)) { printf("click slider photo\r\n"); if(slider_flag == 0){ slider_flag = 1; } else{ slider_flag = 0; } printf("slider_flag = %d\r\n", slider_flag); ts_x = 0; ts_y = 0; } //息屏 else if((ts_y > 360 && ts_y < 480) && (ts_x > 600)) { char command[] = "kill -9 "; char str[10]; sprintf(str, "%d", pid); strcat(command, str); printf("command = %s\r\n", command); //方式一:显示一张黑色的图片 lcd_show_bmp("black.bmp", 0, 0); system(command); } else{ flag_x_y = 0; break; } flag_x_y = 0; } pthread_mutex_unlock(&mutex); } }

 自动播放图片线程处理函数:

void *slider_func(void *arg) { printf("enter slider_func : %d\r\n", pthread_self()); while(1){ if(slider_flag == 1){ printf("enter slider_func\r\n"); touch_flag++; if(touch_flag > BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); sleep(1); } } } 五:Main函数

main函数就是一些线程、互斥锁、条件变量的创建和回收

int main() { lcd_show_bmp("choice.bmp", 600, 0); lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); pthread_t tid, tid_area_switch, tid_right_left_slide; int ret = 0; pthread_create(&tid, NULL, slider_func, NULL); pthread_create(&tid_area_switch, NULL, area_switch, NULL); pthread_create(&tid_right_left_slide, NULL, right_left_slide_func, NULL); pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); printf("main thread = %ld\r\n", pthread_self()); pid = getpid(); printf("pid = %d\r\n", pid); while(1){ get_touch(); } pthread_join(tid, NULL); pthread_join(tid_area_switch, NULL); pthread_join(tid_right_left_slide, NULL); pthread_cond_destroy(&cond); exit(0); } 六:完整代码 #include #include #include #include #include #include #include #include #include #include #include #define BMP_MAX_NUMBER 4 char bmp_path[4][100] = {"1.1.bmp", "1.2.bmp", "1.3.bmp", "1.4.bmp"}; int slider_flag = 0; pid_t pid; pthread_mutex_t mutex; pthread_cond_t cond; //自定义函数:LCD屏幕显示bmp图片 //pathname:需要打开的图片路径 //x0:存放图片显示的x轴起点 //y0:存放图片显示的y轴起点 int lcd_show_bmp(char *pathname, int x0, int y0) { //1、打开设备文件 int lcd = open("/dev/fb0", O_RDWR); if(-1 == lcd) { printf("lcd open error!\n"); return -2; } //2、内存映射 char *ptr = (char *)mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd, 0); if(NULL == ptr) { printf("mmap error!\n"); return -3; } //清除背景色 //bzero(ptr, 800*480*4); //打开图片 int bmp = open(pathname, O_RDWR); if(-1 == bmp) { printf("bmp open error!\n"); return -2; } //读取图片相关信息 int bmp_size, bmp_width, bmp_height; //大小 lseek(bmp, 2, SEEK_SET); read(bmp, &bmp_size, sizeof(bmp_size)); //宽度和高度 lseek(bmp, 18, SEEK_SET); read(bmp, &bmp_width, sizeof(bmp_width)); read(bmp, &bmp_height, sizeof(bmp_height)); //读取图片的颜色数据 lseek(bmp, 54, SEEK_SET); char *bmp_buf = malloc(bmp_size); //申请空间 read(bmp, bmp_buf, bmp_width*bmp_height*3); //对颜色数据进行处理(上下颠倒以及数据混乱) int bmp_sum = 0; int lcd_sum = 0; for(int y=0; y+y0 150) && (old_x < 600))) { right_left_slide_flag = 1; slider_left = 1; old_x = 300; } } } } //4、关闭文件 close(touch_fd); } void *right_left_slide_func(void *arg) { printf("enter right_left_slide_func\r\n"); while(1){ if(right_left_slide_flag == 1){ if(slider_left == 1){ touch_flag--; if(touch_flag BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); slider_right = 0; right_left_slide_flag == 0; } right_left_slide_flag == 0; } } } void *area_switch(void *arg) { printf("enter area_switch\r\n"); while(1){ pthread_mutex_lock(&mutex); while(flag_x_y == 0) pthread_cond_wait(&cond, &mutex); while(flag_x_y == 1){ //上一张 if((ts_y > 0 && ts_y < 120) && (ts_x > 600)) { touch_flag--; if(touch_flag 120 && ts_y < 240) && (ts_x > 600)) { touch_flag++; if(touch_flag > BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); ts_x = 0; ts_y = 0; } //幻灯片 else if((ts_y > 240 && ts_y < 360) && (ts_x > 600)) { printf("click slider photo\r\n"); if(slider_flag == 0){ slider_flag = 1; } else{ slider_flag = 0; } printf("slider_flag = %d\r\n", slider_flag); ts_x = 0; ts_y = 0; } //息屏 else if((ts_y > 360 && ts_y < 480) && (ts_x > 600)) { char command[] = "kill -9 "; char str[10]; sprintf(str, "%d", pid); strcat(command, str); printf("command = %s\r\n", command); //方式一:显示一张黑色的图片 lcd_show_bmp("black.bmp", 0, 0); system(command); } else{ flag_x_y = 0; break; } flag_x_y = 0; } pthread_mutex_unlock(&mutex); } } void *slider_func(void *arg) { printf("enter slider_func : %d\r\n", pthread_self()); while(1){ if(slider_flag == 1){ printf("enter slider_func\r\n"); touch_flag++; if(touch_flag > BMP_MAX_NUMBER) touch_flag = 1; lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); sleep(1); } } } int main() { lcd_show_bmp("choice.bmp", 600, 0); lcd_show_bmp(bmp_path[touch_flag - 1], 0, 0); pthread_t tid, tid_area_switch, tid_right_left_slide; int ret = 0; pthread_create(&tid, NULL, slider_func, NULL); pthread_create(&tid_area_switch, NULL, area_switch, NULL); pthread_create(&tid_right_left_slide, NULL, right_left_slide_func, NULL); pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); printf("main thread = %ld\r\n", pthread_self()); pid = getpid(); printf("pid = %d\r\n", pid); while(1){ get_touch(); } pthread_join(tid, NULL); pthread_join(tid_area_switch, NULL); pthread_join(tid_right_left_slide, NULL); pthread_cond_destroy(&cond); exit(0); } 总结

以上就是本文的全部内容, 希望能够帮助到你。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3