获取BMP图片件并在LCD屏上打开
目录
/*******************************************************************
* file name: ChangeBmp.c
* author : 17666589210@163.com
* date : 2024-05-12
* function : Retrieve images, shrink them, and open them on the LCD screen
* note : None
* CopyRight (c) 2024 17666589210@163.com Right Reseverd
*******************************************************************/
获取BMP文件获取信息进行缩放并产生新的BMP文件并在LCD屏上进行显示
头文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
BMP文件结构体
#pragma pack(1) //设置取消字节对齐
// 文件信息结构体
typedef struct tag_bitmap_file_header
{
unsigned short file_type; // 文件标识,为字母ASCII码“BM”
unsigned int file_size; // 位图文件大小,以字节为单位
unsigned short reserved1; // 位图文件保留字,必须为0
unsigned short reserved2; // 位图文件保留字,必须为0
unsigned int offset_bits; // 文件开始到位图数据开始之间的偏移量字节
}bmp_file_header;
// 位图信息结构体
typedef struct tag_bitmap_info_header
{
unsigned int bitmap_info_size; // 图像描述信息快的大小,常为28H
int bitmap_width; // 图像宽度
int bitmap_height; // 图像高度
unsigned short planes; // 图像的plane总数(恒为1)
unsigned short image_depth; // 记录颜色的位数取值1(双色),4,6,24,,3
unsigned int compression; // 数据压缩方式(0:不压缩;1:8位压缩;2:4位压缩
unsigned int image_size; // 图像区数据的大小,必须是4的倍数
int x_pels_permeter; // 水平每米有多少像素,在设备无关位图中,填写00H
int y_pels_permeter; // 垂直每米有多少像素,在设备无关位图中,填写00H
unsigned int color_used; // 此图像所有的颜色数,不用,固定为0
unsigned int color_important; // 重要颜色数,不用,固定为0
}bmp_info_header;
#pragma pack() //设置为字节对齐
主函数
int main()
{
//1.打开bmp图片文件
FILE * bmp_fp = fopen("demo.bmp","rb");
if(NULL == bmp_fp)
{
printf("open bmp file faild\n");
return -1;
}
//2.读取BMP图片文件的图像信息,获取BMP的宽和高
bmp_info_header headerinfo; //BMP头文件信息结构体
bmp_file_header newheaderinfo1; //为新BMP文件信息的结构体申请内存 14字节
bmp_info_header newheaderinfo; //为新BMP文件信息的结构体申请内 40字节
fseek(bmp_fp,14,SEEK_SET);
fread(&headerinfo,1,40,bmp_fp); //读取BMP头文件信息
printf("current bmp width = %d\ncurrent bmp height = %d\n",headerinfo.bitmap_width,headerinfo.bitmap_height);//输出BMP图片宽度和高度信息
//3.读取原BMP图片的颜色分量
int pxsize = headerinfo.bitmap_width*headerinfo.bitmap_height*headerinfo.image_depth/8;
printf("pxsize = %d\n",pxsize);
char bmp_buf[pxsize]; //申请图片像素大小的缓冲区
fread(bmp_buf,1,pxsize,bmp_fp); //读取BMP颜色分量数据
fseek(bmp_fp,0,SEEK_SET); //设置光标为文件开头
//4.备份当前BMP结构体信息给新BMP文件
fread(&newheaderinfo1,1,14,bmp_fp); //读取BMP头文件信息
newheaderinfo1.file_size = 400*240*3; //设置新BMP图片信息结构体中文件的大小
fread(&newheaderinfo,1,40,bmp_fp); //读取BMP头文件信息
newheaderinfo.bitmap_width = 400; //设置新BMP图片信息结构体中图片的宽度
newheaderinfo.bitmap_height = 240; //设置新BMP图片信息结构体中图片的高度
fclose(bmp_fp); //关闭原BMP文件
char newbmp_buf[pxsize/4]; //申请一块新的BMP图片大小的缓冲区
int cnt = 0;
for(int y = 0;y < 480; y+=2)
{
for(int x = 0; x < 800 ;x+=2)
{
for(int k=0; k<3; k++)
{
newbmp_buf[cnt] = bmp_buf[(y*800+x)*3+k]; //获取三个字节为一组的数据,并隔一行一列获取数据
cnt++;
}
}
}
//printf("%d\n",cnt);//用于调试
//5.打开待写入的文件
FILE * newbmp_fp = fopen("newdemo.bmp","wb+");
if(NULL == newbmp_fp)
{
printf("open bmp file faild\n");
return -1;
}
int fp = fwrite(&newheaderinfo1,1,14,newbmp_fp);
if(fp != 14)
{
printf("write failed\n");
}
fwrite(&newheaderinfo,1,40,newbmp_fp);
fwrite(&newbmp_buf,1,400*240*3,newbmp_fp);
fseek(bmp_fp,54,SEEK_SET); //设置光标为文件颜色分量开头
char Newbmp_buf[pxsize/4];
fread(Newbmp_buf,1,pxsize/4,newbmp_fp);
fclose(newbmp_fp);
//6.打开LCD
int lcd_fd = open("/dev/fb0",O_RDWR);
//7.对LCD进行内存映射
int lcd_pxsize = 800*480*4;
int * lcd_mp = (int *)mmap(NULL,lcd_pxsize,PROT_READ|PROT_WRITE,MAP_SHARED,lcd_fd,0);
//8.循环的把BMP图像的颜色分量依次写入到LCD的像素点中
int i = 0;
int data = 0;
for (int y = 240-1; y >= 0; y--)
{
for (int x = 0; x < 400 ; ++x)
{
//把BMP图片的一个像素点的颜色分量转换为LCD屏幕的一个像素点的颜色分量格式 ARGB <--- BGR
data |= Newbmp_buf[i]; //B
data |= Newbmp_buf[i+1]<<8; //G
data |= Newbmp_buf[i+2]<<16; //R
lcd_mp[800*y + x] = data; //BGR BGR BGR ....
i+=3;
data = 0;
}
}
//8.关闭LCD
close(lcd_fd);
munmap(lcd_mp,lcd_pxsize);
return 0;
}