粤嵌实习-学习bmp文件格式并解析一张bmp图片、交叉开发在开发板上显示一张图片
bmp文件解析并读取信息,将图片显示到开发板上
·
粤嵌实习(电梯运行演示系统)
了解并使用bmp图片和交叉开发
bmp文件格式
bitmap文件头(14字节):
偏移量 | 大小 | 用途 |
---|---|---|
0000H | 2字节 | 用于标识BMP和DIB文件的魔数,一般为0x42 0x4D |
0002H | 4字节 | BMP文件的大小(单位为字节) |
0006H | 2字节 | 保留,实际值因创建程序而异 |
0008H | 2字节 | 保留,实际值因创建程序而异 |
000AH | 4字节 | 位图数据(像素数组)的地址偏移,也就是起始地址。 |
DIB头(40字节):
偏移量 | 大小 | 用途 |
---|---|---|
OEH | 4字节 | 该头结构的大小(40字节) |
12H | 4字节 | 位图宽度,单位为像素(有符号整数) |
16H | 4字节 | 位图宽度,单位为像素(有符号整数) |
1AH | 2字节 | 色彩平面数,只有1为有效值 |
1CH | 2字节 | 每个像素所占位数,即图像的色深,典型值为1、4、8、16、24和32 |
1EH | 4字节 | 所使用的的压缩方法 |
22H | 4字节 | 图像大小。原指位图数据的大小,与文件大小不是同一概念 |
26H | 4字节 | 图像的横向分辨率,单位为像素每米(有符号整数) |
2AH | 4字节 | 图像的纵向分辨率,单位为像素每米(有符号整数) |
2EH | 4字节 | 调色板的颜色数,为0时表示颜色数为默认的2的色深数次方个 |
32H | 4字节 | 重要颜色数,为0时表示所有颜色都是重要的,通常不使用本项 |
调色板(颜色值数组)
像素数组:这部分逐个像素表示图像,每一个像素使用一个或多个字节表示。通常像素是从上到下,从左到右保存的。
应用:读取一张图片的数据
先在共享文件夹下存放一张图片。
编写代码读取图片信息并打印。
int fd = open("./kkk.bmp",O_RDONLY);//共享文件夹下的图片
if(fd == -1)
{
perror("open bmp error:");
return -1;
}
unsigned char buf[64] = {0};
read(fd,buf,64);
//操作
//判断是否为BMP图片
if(buf[0] != 0x42 || buf[1] != 0x4d)
{
printf("NO\n");
close(fd);
return -1;
}
printf("Yes\n");
}
//bmp图片信息的读取
int fd = open(bmpname,O_RDWR);
int size,width,high;
short depth; //两个字节
lseek(fd,2,SEEK_SET);
read(fd,&size,4);//读取图片的大小
lseek(fd,0x12,SEEK_SET);
read(fd,&width,4);//读取图片的宽度
lseek(fd,0x16,SEEK_SET);
read(fd,&high,4);//读取图片的高度
lseek(fd,0x1C,SEEK_SET);
read(fd,&depth,2);//读取图片的色深
printf("bmp size=%d width=%d high = %d depth=%d\n",size,width,high,depth);
结果如下:
交叉开发:
1.连接与配置
(1)连接好开发板,启动开发板。
(2)打开设备管理器,查找识别出的端口号。
若不能正确识别端口号,则需要安装驱动。
(3)使用SecureCRT软件来对开发板进行终端控制。
(4)打开SecureCRT.exe文件,连接开发板。
连接成功:
(5)创建工作文件夹。
①先删除home目录下的所有文件。
cd /home
rm -rf *
②创建并进入自己的工作文件夹,下次使用开发板先进入此文件夹。
mkdir /home/117
cd /home/117
如下:
2.在开发板上运行一个程序
(1)编辑一个C文件,并保存到共享文件夹中。
(2)将其在虚拟机中编译成开发板上可执行文件。
如:
arm-linux-gcc hello.c -o hello
(3)传送可执行文件到开发板上,并执行。
rx 可执行文件名
chmod 0777 可执行文件名
./可执行文件名
应用:读取图片的数据并显示到开发板上
开发板屏幕为800*480。
定义BMP数据结构:
//定义一个bmp图片信息相关的结构体类型
typedef struct BMP
{
char* bmpname; //保存bmp图片的名称
int size; //文件的总大小
int width; //文件的宽
int height; //文件的高
short bpp; //色深
char* data; //像素数组的首地址
}BMP;
定义相关要用到的函数:
//屏幕初始化
void lcd_init();
//解除屏幕初始化
void lcd_uninit();
//画点
void lcd_point(int x,int y,int color);
//获取bmp图片信息
BMP get_bmp_info(char* bmpname);
//画一张bmp图片
void lcd_draw_bmp(char* bmpname, int x, int y);
全部写在bmp.h文件中,具体文件内容如下:
#ifndef __BMP_H
#define __BMP_H
#include <stdio.h>
#include <stdlib.h>
//open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//mmap
#include <sys/mman.h>
//close,read,write
#include <unistd.h>
//定义一个bmp图片信息相关的结构体类型
typedef struct BMP
{
char* bmpname; //保存bmp图片的名称
int size; //文件的总大小
int width; //文件的宽
int height; //文件的高
short bpp; //色深
char* data; //像素数组的首地址
}BMP;
//屏幕初始化
void lcd_init();
//解除屏幕初始化
void lcd_uninit();
//画点
void lcd_point(int x,int y,int color);
//获取bmp图片信息
BMP get_bmp_info(char* bmpname);
//画一张bmp图片
void lcd_draw_bmp(char* bmpname, int x, int y);
#endif
①读取所有像素点的信息。
BMP get_bmp_info(char* bmpname)
{
//可以下载其他格式的图片,在电脑自带的图片编辑中,将图片的像素进行调整,另存为bmp(24位)图片即可
//size --> 0x02 - 4字节 宽 --> 0x12 -- 4字节 高 ->> 0x16 -- 4字节 色深 ->> 0x1c -- 2字节
int fd_bmp = open(bmpname, O_RDONLY);//写入bmp文件名
if (fd_bmp == -1)
{
printf("open bmp error\n");
exit(1);
}
//判断是否是bmp文件
char bm[2] = {0};
read(fd_bmp, bm, 2);
if (!(bm[0] == 'B' && bm[1] == 'M'))
{
printf("%s is not a bmp file\n", bmpname);
exit(1);
}
BMP bmp;
bmp.bmpname = bmpname;
//大小
lseek(fd_bmp, 0x02, SEEK_SET);
read(fd_bmp, &bmp.size, 4);
//宽
lseek(fd_bmp, 0x12, SEEK_SET);
read(fd_bmp, &bmp.width, 4);
//高
read(fd_bmp, &bmp.height, 4);
//色深
lseek(fd_bmp, 0x1c, SEEK_SET);
read(fd_bmp, &bmp.bpp, 2);
//开辟一块空间用来保存像素数组
bmp.data = (char*)malloc(bmp.size - 54);
lseek(fd_bmp, 0x36, SEEK_SET);
read(fd_bmp, bmp.data, (bmp.size-54));
close(fd_bmp);
return bmp;
}
②将图片显示到开发板上。
void lcd_draw_bmp(char* bmpname, int x, int y)
{
BMP bmp = get_bmp_info(bmpname);
//打印图片的基本信息
printf("bmpname = %s, size = %d, width = %d, height = %d, bpp = %hd\n",
bmp.bmpname, bmp.size, bmp.width, bmp.height, bmp.bpp);
//一行的有效字节数
int line_types = abs(bmp.width) * bmp.bpp / 8;
//一行的填充字节数
int pad_types = (line_types % 4 == 0) ? 0 : (4 - (line_types % 4));
int color;
char* p = bmp.data; //遍历指针,遍历整个像素数组
//解析像素数组中的数据并画到开发板上
for (int h = 0; h < abs(bmp.height); h++) //表示行
{
for (int w = 0; w < abs(bmp.width); w++) //表示列
{
char b = *(p++);
char g = *(p++);
char r = *(p++);
char a = (bmp.bpp == 24) ? 0 : *(p++);
color = a << 24 | r << 16 | g << 8 | b;
// width > 0 : 从左到右保存每一个像素点
// width < 0 : 从右到左保存每一个像素点
// height > 0: 从下到上保存每一个像素点
// height < 0: 从上到下保存每一个像素点
int m =x+(bmp.width>0?w:(bmp.width-1-w));
int n =y+(bmp.height<0?h:(bmp.height-1-h));
lcd_point(m, n, color);
}
p += pad_types;//跳过填充字节
}
③编译运行程序
1.先在linux下编译程序。
此处采用了gcc编译同时编译多个c文件,需将各个.c文件和.h文件放在同一个文件夹下。
2.向工作文件夹中传入所需的图片(此处已经传入在开发板中文件名为bg1的图片bg1.bmp)
3.传入并执行文件。
4.结果如下:
更多推荐
已为社区贡献1条内容
所有评论(0)