lcd屏幕相关内容
lcd屏幕相关
- BMP格式图片显示
BMP格式图片显示
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>//lcd驱动节点 引入驱动
#define LCD "/dev/ubuntu_lcd"//映射内存的大小 800*480 *4字节
#define SIZE 800*480*4//无符号int类型
typedef unsigned int * UInt;int main(int argc, char const *argv[])
{//打开设备 打开驱动 只读int lcdfd=open(LCD,O_RDWR);if(lcdfd==-1){perror("驱动打开失败!");return -1;}//通过ioctl获取设备属性struct fb_var_screeninfo info;int ret=ioctl(lcdfd,FBIOGET_VSCREENINFO,&info);if(ret==-1){perror("设备信息加载失败!");return NULL;}//映射 mmap方法映射 1.映射内存的首地址,一般设置为NULL,由系统分配地址 2.映射内存大小,像素宽度高度决定 3.映射权限 port 4.映射的共享权限 5.设备标识符 6.文件偏移量UInt FB=(UInt)mmap(NULL,SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,lcdfd,0);//mmap 如果失败,它会返回 MAP_FAILED。需要根据该值来判断映射是否成功。if(FB==MAP_FAILED){perror("内存映射失败!");return -1;}//打开图片文件信息int bmpfd=open(argv[1],O_RDWR);if(bmpfd==-1){perror("图片打开失败!");return -1;}//读取文件头信息unsigned char info[54]={0};read(bmpfd,info,54);printf("文件标识符:%c %c\n",info[0],info[1] );//总大小unsigned int size = info[2]<<0|info[3]<<8|info[4]<<16|info[5]<<24;printf("文件的总大小:%d\n",size );//宽度 图片的宽度unsigned int bmp_w=info[18]<<0|info[19]<<8|info[20]<<16|info[21]<<24;//图片的高度unsigned int bmp_h=info[22]<<0|info[23]<<8|info[24]<<16|info[25]<<24;printf("图片的宽度:%d 图片的高度:%d\n",bmp_w,bmp_h );//获取图片所有像素点unsigned char * bmpbuf=malloc(bmp_w*bmp_h*3);//读取图片像素点int ret=read(bmpfd,bmpbuf,bmp_w*bmp_h*3);printf("当前读取的图片的总字节数:%d\n",ret );//将BMP图片格式转换成lcd屏幕的格式unsigned int lcdbuf[bmp_w*bmp_h];for (int i = 0; i < bmp_w*bmp_h; ++i){//将图片3字节变成lcd屏幕4字节 通过|运算 比如 0000 | 1111=1111lcdbuf[i]=bmpbuf[3*i+0]<<0|bmpbuf[3*i+1]<<8|bmpbuf[3*i+2]<<16|0x00<<24;}//显示图片到lcd屏幕for (int j = 0; j < bmp_h; ++j)//行{for (int i = 0; i < bmp_w; ++i)//列{//图片像素点赋值到屏幕上FB[i+j*800]=lcdbuf[i+j*bmp_w];}}//关闭图片ret=close(bmpfd);if(ret==-1){perror("图片关闭失败!");return -1;}//关闭映射ret=munmap(FB,SIZE);if(ret==-1){perror("映射关闭失败!");return -1;}//关闭设备ret=close(lcdfd);if(ret==-1){perror("设备关闭失败!");return -1;}return 0;
}
图片的文件标识是从第0个字节开始,一共占2个字节。
图片文件的总大小从第2个字节开始,一共占4个字节。
图片的宽度从第18个字节开始,一共占4个字节。
图片的高度从第22个字节开始,一共占4个字节。
位图中的像素是3个字节,屏幕上的像素是4个字节。屏幕上的像素是4个字节可以用int类型保存,但是C语言中没有3个字节的数据类型,所以位图的像素无法直接保存。
解决方案:
用3个单字节char,分别保存每个字节,然后需要用的时候再组装。
获取点击xy坐标方法方式封装
#ifndef __GET_IMAGE_H__
#define __GET_IMAGE_H__
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <dirent.h>
#include <linux/input.h>
// lcd驱动节点
#define LCD "/dev/ubuntu_lcd"
// 映射内存的大小
#define SIZE 800 * 480 * 4
// 事件驱动节点
#define EVENT "/dev/ubuntu_event"
// 自定义类型
typedef unsigned int *UInt;
// 键盘结构体// LCD设备结构体
struct lcd
{int lcdfd; // lcd文件描述符unsigned int *FB; // 内存映射首地址int ret; // lcd状态描述符
} lcdDev;// 封装打开设备映射内存
int lcd_open();
// 初始化屏幕
void clear_background(unsigned int color);
// 封装关闭int lcd_close();
// 显示图片
int show_bmp(int x, int y, const char *pathname);
// 获取图片的坐标
void get_xy(int *x, int *y);
// // 获取图片路径
// // char *get_path(int *index);
// char **get_path(int *index);
// void clear_background(unsigned int color);#endif
#include "../inc/getImage.h"
#include <string.h>
// 封装打开设备映射内存
int lcd_open()
{// 打开设备lcdDev.lcdfd = open(LCD, O_RDWR);if (lcdDev.lcdfd == -1){perror("驱动打开失败!");return -1;}// 映射lcd的内存lcdDev.FB = (UInt)mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, lcdDev.lcdfd, 0);if (lcdDev.FB == MAP_FAILED){perror("内存映射失败!");return -1;}return lcdDev.lcdfd;
}
// 封装关闭
int lcd_close()
{// 关闭映射内存lcdDev.ret = munmap(lcdDev.FB, SIZE);if (lcdDev.ret == -1){perror("映射内存关闭失败!");return -1;}// 关闭设备lcdDev.ret = close(lcdDev.lcdfd);if (lcdDev.ret == -1){perror("关闭设备失败!");return -1;}return 0;
}// 显示图片
int show_bmp(int x, int y, const char *pathname)
{// 打开图片int bmpfd = open(pathname, O_RDWR);if (bmpfd == -1){perror("图片打开失败!");return -1;}// 读取54个字节的头信息unsigned char info[54] = {0};read(bmpfd, info, 54);if (info[0] != 'B' && info[1] != 'M'){perror("该图片格式错误,不是BMP图!");return -1;}// 获取图片宽度和高度// 宽度unsigned int bmp_w = info[18] << 0 | info[19] << 8 | info[20] << 16 | info[21] << 24;// 高度unsigned int bmp_h = info[22] << 0 | info[23] << 8 | info[24] << 16 | info[25] << 24;// printf("图片的宽度:%d 图片的高度:%d\n", bmp_w, bmp_h);// 读取像素点unsigned char *bmpbuf = malloc(bmp_w * bmp_h * 3);int ret = read(bmpfd, bmpbuf, bmp_w * bmp_h * 3);// 将BMP图片的格式转换成LCD屏幕的格式unsigned int lcdbuf[bmp_w * bmp_h];for (int i = 0; i < bmp_w * bmp_h; ++i){lcdbuf[i] = bmpbuf[3 * i + 0] << 0 | bmpbuf[3 * i + 1] << 8 | bmpbuf[3 * i + 2] << 16 | 0x00 << 24;}// 显示图片到lcd屏幕上for (int j = 0; j < bmp_h; ++j) // 行{for (int i = 0; i < bmp_w; ++i) // 列{lcdDev.FB[(x + i) + (y + j) * 800] = lcdbuf[i + (bmp_h - 1 - j) * bmp_w];}}// 关闭图片lcdDev.ret = close(bmpfd);if (lcdDev.ret == -1){perror("图片关闭失败!");return -1;}return 0;
}
// 初始化图片
void clear_background(unsigned int color){for (int i = 0; i < 800 * 480; ++i){lcdDev.FB[i] = color;}
}// 获取点击图片坐标void get_xy(int *x, int *y)
{*x = -1;*y = -1;// 打开文件int tsfd = open(EVENT, O_RDONLY);if (tsfd == -1){perror("驱动打开失败!");return;}// 读取数据struct input_event data;while (1){int size = read(tsfd, &data, sizeof(data));if (size < 0){perror("读取失败!");return;}if (data.type == EV_ABS && data.code == ABS_X){*x = data.value;}else if (data.type == EV_ABS && data.code == ABS_Y){*y = data.value;if (*x > 0){break;}}}
}