设计程序实现在LCD上任意位置显示一张任意大小的色深为 24bit的bmp图片,要求图像不失真可以在开发板的LCD上显示。
头文件包含
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <strings.h>
//以1字节对齐方式对齐
#pragma pack(1)
// 定义BMP文件头部结构
typedef struct
{
unsigned short bfType;
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
} BITMAPFILEHEADER;
typedef struct
{
unsigned int biSize;
int biWidth; // 宽
int biHeight; // 高
unsigned short biPlanes;
unsigned short biBitCount; // 色深
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BITMAPINFOHEADER;
//取消字节对齐
#pragma pack()
/*******************************************************************
*
* 函数名称: ShowBmp
* 函数功能: 在LCD上任意位置显示一张任意大小的色深为 24bit的bmp图片
* 函数参数:
* @name bmp图像文件名
* @x 图像显示的起点x轴坐标
* @y 图像显示的起点y轴左边
* @lcd_mp lcd屏内存映射的地址
* 返回结果:
* 注意事项: None
* 函数作者: [email protected]
* 创建日期: 2024/05/12
* 修改历史:
* 函数版本: V1.0
* *****************************************************************/
int ShowBmp(char *name, int x, int y, int *lcd_mp)
{
// 1.打开待显示的BMP图像 fopen
FILE *bmp_fp = fopen(name, "rb");
if (NULL == bmp_fp)
{
printf("open FILE is error!\n");
return -1;
}
// 2.读取BMP文件的图像信息,获取BMP的宽和高
BITMAPINFOHEADER headinfo;
fseek(bmp_fp, 14, SEEK_SET);
fread(&headinfo, 1, 40, bmp_fp); // 读取40字节
// 打开LCD open
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
{
printf("mmap for lcd is error\n");
return -1;
}
// 调用LCD屏的像素
struct fb_var_screeninfo lcd_vinfo;
ioctl(lcd_fd, FBIOGET_VSCREENINFO, &lcd_vinfo);
// 3.读取BMP图片的颜色分量
char bmp_buf[headinfo.biWidth * headinfo.biHeight * 3];
bzero(bmp_buf, headinfo.biWidth * headinfo.biHeight * 3);
fread(bmp_buf, 1, headinfo.biWidth * headinfo.biHeight * 3, bmp_fp);
printf("bmp width = %d,height = %d\n", headinfo.biWidth, headinfo.biHeight);
// 4.关闭BMP
fclose(bmp_fp);
// 5.循环将bmp图像写入lcd屏指定位置
int data = 0;
int i = 0;
for (int h = (y + headinfo.biHeight - 1); h >= y; h--)
{
for (int w = x; w < (x + headinfo.biWidth); w++)
{
data |= bmp_buf[i];
data |= bmp_buf[i + 1] << 8;
data |= bmp_buf[i + 2] << 16;
lcd_mp[h * (lcd_vinfo.xres) + w] = data;
i += 3;
data = 0;
}
}
// 关闭LCD
close(lcd_fd);
munmap(lcd_mp, lcd_vinfo.xres * lcd_vinfo.yres * 4);
return 0;
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("argument is error!\n");
return -1;
}
if (NULL == argv[1])
{
printf("argument 2 is error!\n");
return -1;
}
// 打开LCD open
int lcd_fd = open("/dev/fb0", O_RDWR);
if (lcd_fd == -1)
{
printf("mmap for lcd is error\n");
return -1;
}
// 调用LCD屏的像素
struct fb_var_screeninfo lcd_vinfo;
ioctl(lcd_fd, FBIOGET_VSCREENINFO, &lcd_vinfo);
// 对LCD进行内存映射 mmap
int *lcd_mp = (int *)mmap(NULL,
lcd_vinfo.xres * lcd_vinfo.yres * 4,
PROT_READ | PROT_WRITE,
MAP_SHARED,
lcd_fd,
0);
// 键盘输入图片显示的起始位置
int x, y;
scanf("%d%d", &x, &y);
ShowBmp(argv[1], x, y, lcd_mp);
// 关闭LCD
munmap(lcd_mp, lcd_vinfo.xres * lcd_vinfo.yres * 4);
close(lcd_fd);
return 0;
}
测试结果