练习: 现在开发板中有一个目录叫pic_dir,里面存放着???张800*480的24位bmp格式图片
现在要求你写一个程序,当程序开始运行时,先显示pic_dir目录下第一张图片,然后点击触摸屏的左边区域松手,就显示上一张图片
点击触摸屏的右边区域松手,就显示下一张图片,点击触摸屏中间区域松手,就显示黑屏并退出程序。
如果当前显示第一张,那么点击左边,就显示最后一张。
如果当前显示最后一张,那么点击右边,就显示第一张。
————————————————
程序如下:”
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/input.h>
/*
数据处理步骤
1.open函数打开设备文件/dev/fb0
2.fopen函数打开图片文件
3.准备图片缓冲区bmp_buf和设备缓冲区lcd_buf,跳过图片数据前54个头数据
4.将图片文件拷贝到bmp_buf中,进行24位转32位操作后存储在lcd_buf中,在对图像数据进行上下颠倒操作,再把图像数据文件拷贝到存储在show_buf中
5.用内存映射方式申请内存空间,将show_bmp中的数据拷贝到内存中去,最后释放内存
*/
//普通文件打开方式来访问文件
int show_pic(const char*picname)
{
//打开开发版/dev/fb0 lcd 液晶设备
int lcd;
lcd = open("/dev/fb0",O_RDWR);
if(lcd < 0)
{
printf("open /dev/fb0 error!\n");
}
//打开指定路径下图片文件
FILE*fp = fopen("/text.bmp","r");
if(fp == NULL)
printf("fopen text.bmp error!\n");
char bmp_buf[800*480*3]={0};
char lcd_buf[800*480*4]={0};
//将文件读入图片缓冲区
fread(bmp_buf,800*480*3,1,fp);
//在bmp_buf缓冲区中进行操作,由于bmp格式图片是24位图,图片数据需要经过”24位转32位“的转换
//转化完毕存储在lcd_buf中
int i,j;
for(i=0,j=0;i<800*480*4;i+=4,j+=3)
{
lcd_buf[i] = bmp_buf[i];
lcd_buf[i+1] = bmp_buf[j+1];
lcd_buf[i+2] = bmp_buf[j+2];
lcd_buf[i+3] =0;
}
//对缓冲区的图像进行上下颠倒处理操作,防止图片显示出现错误
int x,y;
char show_buf[800*480*4] = {0};
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];
}
}
//将缓冲区的数据写入lcd 液晶设备中
write(lcd,show_buf,sizeof(show_buf));
close(lcd);
fclose(fp);
return 0;
}
//通过内存映射来打开访问文件
void mmap_show_buf(const char*picname)
{
//打开开发板/dev/fb0 液晶设备中
int lcd;
lcd = open("/dev/fb0",O_RDWR);
if(lcd<0)
{
printf("open /dev/fb0 error!\n");
}
//打开传入的文件内容
FILE*fp = NULL;
fp = fopen(picname,"r");
if(fp == NULL)
{
printf("fopen picname error!\n");
}
//跳过图片开头54个头数据
fseek(fp,54,SEEK_SET);
char bmp_buf[800*480*3] = {0};//bmp格式文件为24 位图,只包含3个字节
char lcd_buf[800*480*4] = {0};
//将图片数据写入图片缓冲区中待处理
fread(bmp_buf,800*480*3,1,fp);
//将图片数据经过"24位转32位"处理,存入lcd缓冲区
int i,j;
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;
}
//将图片像素数据进行上下颠倒处理
int x,y;
//定义一个缓冲区来接住lcd缓冲区中待上下颠倒处理数据
char show_buf[800*480*4] = {0}; //每一个小元素都是char
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];
}
}
//在内存中映射一份内存空间来存放图片数据
char *p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
if(p == NULL)
printf("mmap error!\n");
//不断将show_buf中的内容放置到申请的内存空间中
int k;
for(k=0;k<800*480*4;k++)
{
memcpy(p+k,&show_buf[k],1);
}
//对申请的内存空间进行释放操作
munmap(p,800*480*4);
}
//-----------------------------------------------------------------------------------------------------
/*事件结构体 --> 专门用于描述一个事件的
struct input_event {
struct timeval time; //发生事件的时间
__u16 type; //事件类型 --> 鼠标发生事件/ 键盘发生事件 /触摸屏发生事件
__u16 code; //事件的编码 --> 左键/右键/滚轮 A键/B键 x轴/y轴/压力
__s32 value; //事件的值 --> 专门用于描述状态
};
//
* Event types事件类型选择
#define EV_KEY --> 按键事件(键盘/触摸屏压力) 0x01
#define EV_REL --> 相对位移事件(鼠标) 0x02
#define EV_ABS --> 绝对位移事件(触摸屏坐标) 0x03
//Event code 事件的编码选择
#define BTN_TOUCH --> 触摸屏压力 0x14a
#define ABS_X --> x轴 0x00
#define ABS_Y --> y轴 0x01
*/
//-------------------------------------------------------------------------------------------------------
int mmap_show_color(int color)
{
//打开开发板/dev/fb0 lcd液晶设备
int lcd;
lcd = open("/dev/fb0",O_RDWR);
if(lcd < 0)//打开失败
{
printf("open /dev/fb0 error!\n");
}
//采用内存映射分配内存空间
int *p;
p = mmap(NULL,800*480*4,PROT_READ|PROT_WRITE,MAP_SHARED,lcd,0);
if(p < 0)
{
printf("open mmap error!\n");
}
int i;
for(i=0;i<800*480;i++)
{
memcpy(p+i,&color,4);
}
//撤销映射
munmap(p,800*480*4);
//关闭文件。
close(lcd);
return 0;
}
int main(int argc,char *argv[])
{
//显示当前路径下指定图片
//show_pic("text.bmp");
//mmap_show_buf("test.bmp");
//定义存储文件路径的缓冲区数组,指定路径下图片
char*picname[5]={"/bmp_dir/1.bmp","/bmp_dir/2.bmp","/bmp_dir/3.bmp","/bmp_dir/4.bmp","/bmp_dir/5.bmp"};
int i;
mmap_show_buf(picname[i]);
//进入触摸屏状态,打开开发板/dev/input/event0 触摸屏文件
int fd;
fd = open("/dev/input/event0",O_WRONLY);
if(fd <0)
printf("open /dev/input/event0 error!\n");
//触摸屏信息结构体
struct input_event buf;
//进行循环读取操作
int x;
while(1)
{
read(fd,&buf,sizeof(buf));
//判断触摸屏事件类型是否为相对位移事件,事件编码为x轴
if(buf.type == EV_ABS && buf.code == ABS_X)
{ //事件的值为x
x = buf.value;
}
//判断触摸屏事件类型是否为按键类型,事件编码为压力类型,时间的值为0
if(buf.type == EV_KEY && buf.code == BTN_TOUCH && buf.value == 0)
{ //检测到按键相对位移横坐标小于341,显示picname[4]
if(x<341)
{
if(i == 0)
{
i = 4;
}
else{
i--;
}
mmap_show_buf(picname[i]);
}
//检测到按键相对位移横坐标大于341&&小于682,显示color
if(x > 341 && x <682)
mmap_show_color(0x0103FB07);
break;
if(x>682)
{
if(i==4)
{
i == 0;
}
else{
i++;
}
mmap_show_buf(picname[i]);
}
}
}
return 0;
}
24位转32位思路图: