前段时间做了一个项目,用到了linux环境下gec6818开发板显示bmp文件,在这里给大家分享一下。
要在LCD上显示bmp图片首先要打开lcd文件
/*LCD文件*/ lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd < 0) { printf("打开LCD文件失败\n"); return -1; } printf("LCD文件初始化完毕\n");
如果用直接写rgb值的方法回导致屏幕刷新特别慢,所以这里使用的是内存映射的方法
/*内存映射*/ FB = (int *)mmap(NULL, 800*480*4, PROT_READ | PROT_WRITE, MAP_SHARED,lcd_fd, 0); printf("内存映射完毕\n");
然后是调用bmp显示函数,这里用两个函数分别显示全屏图片和任意大小图片
/* 功能:显示800*480大小的bmp图片。 参数: char *pathname:要显示图片的名字。 int *show_1152000bmp_fd:被映射区的指针。 返回值:成功 0 失败 -1 */ int show_1152000bmp(char *pathname, int *show_1152000bmp_fd) { //1、打开BMP格式图片和lcd显示屏 int fd_bmp = open(pathname, O_RDWR); if(fd_bmp == -1) { printf("show_1152000bmp(), open bmp fail!\n"); return -1; } //2、去掉54个字节 int ret = lseek(fd_bmp, 54, SEEK_SET); if(ret == -1) { printf("show_1152000bmp(), lseek bmp fail!\n"); return -1; } //3、读取BMP数据到lcd屏幕中 char bmp_buf[800*480*3]; int lcd_buf[800*480]; bzero(bmp_buf, 800*480*3); bzero(lcd_buf, 800*480); ret = read(fd_bmp, bmp_buf, 800*480*3);//BMP数据放到了bmp_buf中 if(ret == -1) { printf("show_1152000bmp(), read bmp fail!\n"); return -1; } //4、关闭文件,回收资源 close(fd_bmp); //5、800*480个A像素变成800*480个B像素算法。 int i; for(i=0; i<800*480; i++) { lcd_buf[i] = bmp_buf[i*3]<<0 | bmp_buf[i*3+1]<<8 | bmp_buf[i*3+2]<<16; //lcd_buf[0] = bmp_buf[0]<<0 | bmp_buf[1]<<8 | bmp_buf[2]<<16; //lcd_buf[1] = bmp_buf[3]<<0 | bmp_buf[4]<<8 | bmp_buf[5]<<16; //lcd_buf[2] = bmp_buf[6]<<0 | bmp_buf[7]<<8 | bmp_buf[8]<<16; } //6、lcd_buf数据(DDR2中的数据)通过mmap显示到LCD屏幕中。 /* for(i=0; i<800*480; i++) { *(lcd_mmap+i)=lcd_buf[i]; } */ int x, y; for(y=0; y<480; y++)//优化算法,解决图片颠倒问题 { for(x=0; x<800; x++) { *(show_1152000bmp_fd+800*(479-y)+x)= lcd_buf[800*y+x]; } } return 0; } /* 功能:(不超过800*480显示屏大小)显示任意位置任意大小的bmp图片 形参: char *pathname:要显示图片的名字 int lcd_x_coordinates:lcd屏的x轴坐标 int lcd_y_coordinates:lcd屏的y轴坐标(通过x、y轴坐标确定显示图片起始显示坐标) int wide:所显示图片的宽度 int height:所显示图片的高度 int *show_bmp_lcd_mmap:被映射区的指针 返回值:成功 0 失败 -1 */ int show_location_bmp(char *pathname,int lcd_x_coordinates, int lcd_y_coordinates, int wide, int height,int *show_bmp_lcd_mmap) { int i; int ret; int x, y; char bmp_buf[wide*height*3]; int new_buf[wide*height]; bzero(bmp_buf, sizeof(bmp_buf)); bzero(new_buf, sizeof(new_buf)); int bmp_fd = open(pathname, O_RDONLY);//1、打开BMP格式图片 if(bmp_fd == -1) { printf("show_location_bmp(), open bmp failed\n"); return -1; } ret = lseek(bmp_fd,54,SEEK_SET);//2、跳过bmp图片的前54个位置 if(ret == -1) { printf("show_location_bmp(), lseek bmp failed\n"); return -1; } int *new_p = show_bmp_lcd_mmap + 800*lcd_y_coordinates + lcd_x_coordinates;//3、重新确定映射位置。 ret = read(bmp_fd, bmp_buf, wide*height*3);//4、取读图片像素 if(ret == -1) { printf("show_location_bmp(), read bmp failed\n"); return -1; } close(bmp_fd);//5、关闭图片 for(i=0; i<wide*height; i++)//6、24bits 转 32bits控制变量 { new_buf[i] = bmp_buf[i*3]<<0 | bmp_buf[(i*3)+1]<<8 | bmp_buf[(i*3)+2]<<16; } for(y=0;y<height;y++)//7、解决图片上下颠倒问题 { for(x=0;x<wide;x++) { *(new_p+(800*((height-1)-y))+x) = new_buf[wide*y+x]; } } return 0; }
最后是解除内存映射,关闭lcd文件
/*解除内存映射*/ munmap(FB, 800*480*4); printf("内存映射解除完毕\n"); /*关闭LCD*/ close(lcd_fd); printf("LCD关闭完毕\n");
代码实测可用,下面再附上一些bmp图片的特效显示函数
/* 功能:切换BMP图片特效“圆形扩散”。 参数: char *pathname:图片的路径。 int *pic_circular_spread_fd:被映射区的指针。 返回值:成功 0 失败 -1 */ int pic_circular_spread(char *pathname, int* pic_circular_spread_fd) { int ret=0; int line=0; int block=0; int i=0, j=0, k=0; int bmp_fd=0; char bmp_buf[480*800*3]; int mi_buf[480*800]; int temp_buf[480*800]; bzero(mi_buf,sizeof(mi_buf)); bzero(bmp_buf,sizeof(bmp_buf)); bzero(temp_buf,sizeof(temp_buf)); bmp_fd = open(pathname, O_RDONLY);//1、打开BMP格式图片 if(bmp_fd == -1) { printf("pic_circular_spread(), open bmp failed\n"); return -1; } ret = lseek(bmp_fd, 54 , SEEK_SET);//2、跳过bmp图片的前54个位置 if(ret == -1) { perror("pic_circular_spread(), lseek bmp failed\n"); return -1; } ret = read(bmp_fd , bmp_buf , sizeof(bmp_buf)); //4、取读图片像素 if(ret == -1) { printf("pic_circular_spread(), read bmp failed\n"); return -1; } close(bmp_fd);//5、关闭图片 for(i=0, j=0 ; i<800*480 ; i++, j+=3)//6、24bits 转 32bits控制变量 { temp_buf[i] = bmp_buf[j+2]<<16 | bmp_buf[j+1]<<8 | bmp_buf[j] ; } for(line=0 ; line <=480 ;line++)//7、解决图片上下颠倒问题 { for(i=0; i<=800 ; i++) mi_buf[800*line + i] = temp_buf[ (479-line)*800 + i ]; } for(k=0; k<467; k+=3)//8、特殊动画“圆形扩散”效果算法 { for(i=0; i<480; i++) { for(j=0; j<800; j++) { if((j-400)*(j-400)+(i-240)*(i-240) <= k*k) { pic_circular_spread_fd[800*i+j] = mi_buf[800*i+j]; } } } } return 0; } /* 功能:切换BMP图片特效”圆形收缩“。 参数: char *pathname:图片的路径。 int *pic_circular_shrink_fd:被映射区的指针。 返回值:成功 0 失败 -1 */ int pic_circular_shrink(char *pathname, int* pic_circular_shrink_fd) { int ret=0; int line=0; int block=0; int i=0, j=0, k=0; int bmp_fd=0; char bmp_buf[480*800*3]; int mi_buf[480*800]; int temp_buf[480*800]; bzero(mi_buf,sizeof(mi_buf)); bzero(bmp_buf,sizeof(bmp_buf)); bzero(temp_buf,sizeof(temp_buf)); bmp_fd = open(pathname , O_RDONLY);//1、打开BMP格式图片 if(bmp_fd == -1) { printf("pic_circular_shrink(), open bmp failed\n"); return -1; } ret = lseek(bmp_fd, 54 , SEEK_SET);//2、跳过bmp图片的前54个位置 if(ret == -1) { perror("pic_circular_shrink(), lseek bmp failed\n"); return -1; } ret = read(bmp_fd , bmp_buf , sizeof(bmp_buf)); //4、取读图片像素 if(ret == -1) { printf("pic_circular_shrink(), read bmp failed\n"); return -1; } close(bmp_fd);//5、关闭图片 for(i=0, j=0 ; i<800*480 ; i++, j+=3)//6、24bits 转 32bits控制变量 { temp_buf[i] = bmp_buf[j+2]<<16 | bmp_buf[j+1]<<8 | bmp_buf[j] ; } for(line=0 ; line <=480 ;line++)//7、解决图片上下颠倒问题 { for(i=0; i<=800 ; i++) mi_buf[800*line + i] = temp_buf[ (479-line)*800 + i ]; } //8、特殊动画“圆形收缩”效果算法 for(k=468; k>=0; k-=3) { for(i=0; i<480; i++) { for(j=0; j<800; j++) { if((j-400)*(j-400)+(i-240)*(i-240) >= k*k) pic_circular_shrink_fd[800*i+j] = mi_buf[800*i+j]; } } } return 0; } /* 功能:切换BMP图片特效”向下飞入“。 参数: char *pathname:图片的路径。 int *pic_down_fd:被映射区的指针。 返回值:成功 0 失败 -1 */ int pic_down(char *pathname, int* pic_down_fd) { int ret=0; int line=0; int block=0; int i=0, j=0, k=0; int bmp_fd=0; char bmp_buf[480*800*3]; int mi_buf[480*800]; int temp_buf[480*800]; bzero(mi_buf,sizeof(mi_buf)); bzero(bmp_buf,sizeof(bmp_buf)); bzero(temp_buf,sizeof(temp_buf)); bmp_fd = open(pathname , O_RDONLY);//1、打开BMP格式图片 if(bmp_fd == -1) { printf("pic_down(), open bmp failed\n"); return -1; } ret = lseek(bmp_fd, 54 , SEEK_SET);//2、跳过bmp图片的前54个位置 if(ret == -1) { perror("pic_down(), lseek bmp failed\n"); return -1; } ret = read(bmp_fd , bmp_buf , sizeof(bmp_buf)); //4、取读图片像素 if(ret == -1) { printf("pic_down(), read bmp failed\n"); return -1; } close(bmp_fd);//5、关闭图片 for(i=0, j=0 ; i<800*480 ; i++, j+=3)//6、24bits 转 32bits控制变量 { temp_buf[i] = bmp_buf[j+2]<<16 | bmp_buf[j+1]<<8 | bmp_buf[j] ; } for(line=0 ; line <=480 ;line++)//7、解决图片上下颠倒问题 { for(i=0; i<=800 ; i++) mi_buf[800*line + i] = temp_buf[ (479-line)*800 + i ]; } //8、特殊动画“向下飞入”效果算法 for(i=0; i<480; i++) { for(j=0; j<800; j++) { pic_down_fd[800*i+j] = mi_buf[800*i+j]; } usleep(1000); } return 0; } /* 功能:切换BMP图片特效”向上飞入“。 参数: char *pathname:图片的路径。 int *pic_up_fd:被映射区的指针。 返回值:成功 0 失败 -1 */ int pic_up(char *pathname, int* pic_up_fd) { int ret=0; int line=0; int block=0; int i=0, j=0, k=0; int bmp_fd=0; char bmp_buf[480*800*3]; int mi_buf[480*800]; int temp_buf[480*800]; bzero(mi_buf,sizeof(mi_buf)); bzero(bmp_buf,sizeof(bmp_buf)); bzero(temp_buf,sizeof(temp_buf)); bmp_fd = open(pathname , O_RDONLY);//1、打开BMP格式图片 if(bmp_fd == -1) { printf("pic_up(), open bmp failed\n"); return -1; } ret = lseek(bmp_fd, 54 , SEEK_SET);//2、跳过bmp图片的前54个位置 if(ret == -1) { perror("pic_up(), lseek bmp failed\n"); return -1; } ret = read(bmp_fd , bmp_buf , sizeof(bmp_buf)); //4、取读图片像素 if(ret == -1) { printf("pic_up(), read bmp failed\n"); return -1; } close(bmp_fd);//5、关闭图片 for(i=0, j=0 ; i<800*480 ; i++, j+=3)//6、24bits 转 32bits控制变量 { temp_buf[i] = bmp_buf[j+2]<<16 | bmp_buf[j+1]<<8 | bmp_buf[j] ; } for(line=0 ; line <=480 ;line++)//7、解决图片上下颠倒问题 { for(i=0; i<=800 ; i++) mi_buf[800*line + i] = temp_buf[ (479-line)*800 + i ]; } //8、特殊动画“向上飞入”效果算法 for(i=479; i>=0; i--) { for(j=0; j<800; j++) { pic_up_fd[800*i+j] = mi_buf[800*i+j]; } usleep(500); } return 0; }
我最近建了一个嵌入式的QQ交流群,感兴趣的可以进群了解一下,我会在群里分享一些常用的代码封装,以及一些项目的源码。QQ群讨论也是完全开放,只要不打广告大家可以就嵌入式尽情的沟通和交流,大家对文章中的内容有疑问也可以在群中提出,有空会尽我所能给大家一些帮助。QQ群号:643408467