文件IO以及图片显示

接上一篇讲到了lseek偏移量,

文件空洞

文件空洞是指:文件中某些部分没有实际存储数据,但是占用了磁盘空间

作用: 1.节省存储空间        2.提高文件读写效率        3.支持稀疏文件

例如下面的例子

 液晶屏的基本概念

像素:

屏幕上显示颜色的最小单位,英文名pixel

分辨率:

宽,高两个维度上的像素点数目,分辨率越高所需要的显存越大。

色深:

每个像素所对应的内存字节数,一般有8位,16位,24位,32位,32位色深的屏幕一般被称为真彩屏。

色深决定了一个像素点所能表达的颜色的丰富程度,色深越大,色彩表现力越强。

内存映射基本原理mmap()

注意几点:

1.使用mmap内存映射时,指定的读写权限必须是打开模式的子集。

2.映射模式为MAP_SHSRED时,修改的内容会影响文件。

3.映射模式为MAP_PRIVATE时,修改的内容不会影响文件。

 屏幕参数设定

屏幕的硬件参数,都是有硬件驱动工程师根据硬件数据手册和内核的相关规定,填入某个固定的地方的(指的是源码,结构体),再有开发工程师使用特定的函数接口,将源码里面的信息读出来

 

 输入子系统

 

在linux的内核中,对输入设备的使用,实际运用的三大块来管理,分别是输入设备驱动层,输入子系统核心层,以及时间触发层。各自的工作分别是:

1.输入设备驱动层:

每一种设备都有其特定的驱动程序,他们被装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。

2.核心层:

此处将收集由设备驱动层发来的数据,整合之后触发某一事件。

3.事件触发层:

这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件,来获知某设备的某一动作。

输入信息结构体

内核所获知的各类输入事件,比如滑动屏幕,键盘被按了一下等,都将被统一封装在一个叫做input_event的输入信息结构体中

 该结构体有4个成员

1.time:

输入时间发生的时间戳,精确到微秒。

2.type:

输入事件的类型,比如:

3.code :

对事件类型做进一步描述。比如:

 4.value:

当code 都不足以区分事件的性质的时候,可以用value来确认。

触摸屏操作 

对于触摸屏而言会产生三种数据:X轴坐标值    Y轴坐标值     P压力值

滑屏显示坐标,松手退出

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h> 

int main(int argc, char const *argv[])
{
    int ts_x,ts_y;
    // 非阻塞打开触摸屏设备
    //int ts_fd = open("/dev/input/event1",O_RDWR|O_NONBLOCK);
    // 阻塞打开触摸屏设备
    int ts_fd = open("/dev/input/event1",O_RDWR);
    if(ts_fd == -1)
    {
        perror("open ts failed:");
        return -1;
    }

    struct input_event ts_event = {0};
    // 循环读取事件
    while(1)
    {
        read(ts_fd, &ts_event, sizeof(ts_event));
        if(ts_event.type == EV_ABS && ts_event.code == ABS_MT_POSITION_X)
        {
            ts_x = ts_event.value;
        }
        if(ts_event.type == EV_ABS && ts_event.code == ABS_MT_POSITION_Y)
        {
            ts_y = ts_event.value;
        }

        // 判断持续事件,并且连续事件结束后打印坐标值
        if(ts_event.type == EV_SYN && ts_event.code == SYN_REPORT)
        {
            printf("(%d,%d)\n",ts_x,ts_y);
        }
        // 松手
        if(ts_event.code == ABS_MT_TRACKING_ID && ts_event.value == -1)
        {
            break;
        }
    }
    // 关闭ts
    close(ts_fd);
    return 0;
}

显示BMP图片流程

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>

int main(int argc, char const *argv[])
{
    // 打开lcd设备文件
    int lcd_fd = open("/dev/fb0",O_RDWR);
    if(lcd_fd == -1)
    {
        perror("open lcd failed:");
        return -1;
    }

    // 打开bmp图片
    int bmp_fd = open("./dog.bmp",O_RDWR);
    if(bmp_fd == -1)
    {
        perror("open bmp failed:");
        return -1;
    }

    // 跳过54字节bmp头信息
    lseek(bmp_fd, 54, SEEK_SET);

    // 读取图片数据
    char buf[1024*600*3] = {0};
    read(bmp_fd, buf, sizeof(buf));

    // 将3字节的bmp数据转为4字节的bmp数据
    int bmp_buf[1024*600] = {0};
    int i,j;
    for(i = 0,j = 0; i < 1024*600; i++,j+=3)
    {
        bmp_buf[i] = buf[0+j] << 0 | buf[1+j] << 8 | buf[2+j] << 16 | 0x0 << 24;
    }

    // 图片进行翻转
    int lcd_buf[1024*600] = {0};
    int x,y;
    for(y = 0; y < 600; y++)
    {
        for(x = 0; x < 1024; x++)
        {
            lcd_buf[y*1024+x] = bmp_buf[(599-y)*1024+x];
        }
    }

    // 将bmp写入到lcd
    write(lcd_fd, lcd_buf, sizeof(lcd_buf));

    // 关闭lcd
    close(lcd_fd);
    close(bmp_fd);

    return 0;
}

 通过mmap内存映射显示图片

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>

void showBmp(const char *bmp_path)
{
    // 打开lcd
    int lcd_fd = open("/dev/fb0",O_RDWR);
    if(lcd_fd == -1)
    {
        perror("open lcd failed:");
        return ;
    }

    // lcd映射
    int *lcd_ptr = mmap(NULL, 
                        1024*600*4, 
                        PROT_READ|PROT_WRITE, 
                        MAP_SHARED,
                        lcd_fd,
                        0 );
    if(lcd_ptr == NULL)
    {
        perror("mmap failed:");
        return ;
    }

    // 打开图片
    int bmp_fd = open(bmp_path,O_RDWR);
    if(bmp_fd == -1)
    {
        perror("oopen bmp failed");
        return ;
    }

    // 跳过54字节头信息
    lseek(bmp_fd, 54, SEEK_SET);

    // 读取图片
    char buf[1024*600*3] = {0};
    read(bmp_fd,buf,sizeof(buf));
    // 关闭图片
    close(bmp_fd);

    // 将3字节转为4字节
    int i,j;
    int bmp_buf[1024*600] = {0};
    for(i = 0, j = 0; i < 1024*600; i++,j+=3)
    {
        bmp_buf[i] = buf[j+0] << 0 | buf[j+1] << 8 | buf[j+2] << 16;
    }

    // 翻转
    int x, y;
    for(y = 0; y < 600; y++)
    {
        for(x = 0; x < 1024; x++)
        {
            lcd_ptr[y*1024+x] = bmp_buf[(599-y)*1024+x];
        }
    }

    // 解除映射,关闭设备
    munmap(lcd_ptr,1024*600*4);
    close(lcd_fd);
}

int main(int argc, char const *argv[])
{
    // 显示图片
    showBmp("./dog.bmp");
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值