内存映射和普通IO区别,以图片显示为例

练习: 现在开发板中有一个目录叫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位思路图:

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖爱Kun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值