LV18-01-LCD应用编程-03-显示BMP图片

本文主要是LCD应用编程——显示BMP图片的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.2的64位版本
VMware® Workstation 17 Pro 17.6.0 build-24238078
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
Linux开发板环境 Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
其他网站 kernel - Linux source code (v4.15) - Bootlin linux内核源码在线查看
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
https://elixir.bootlin.com/linux/latest/source 在线阅读linux kernel源码
nxp-imx/linux-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP linux内核仓库tags中的rel_imx_4.1.15_2.1.0_ga
nxp-imx/uboot-imx/releases/tag/rel_imx_4.1.15_2.1.0_ga NXP u-boot仓库tags中的rel_imx_4.1.15_2.1.0_ga
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)

一、BMP图片格式

这个可以直接看《01嵌入式开发/04音视频/LV01-图像基础知识/LV01-图像-03-图片格式-02-BMP.md》这篇笔记,这篇笔记详细学习了BMP文件格式。不过这里还是简单的再了解一下。

1. BMP 图像介绍

我们常用的图片格式有很多,一般最常用的有三种: JPEG(或 JPG)、 PNG、 BMP 和 GIF。其中 JPEG(或 JPG)、 PNG 以及 BMP 都是静态图片,而 GIF 则可以实现动态图片。

BMP(全称 Bitmap)是 Window 操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用非常广。它采用位映射存储格式,除了图像深度可选以外,图像数据没有进行任何压缩,因此, BMP 图像文件所占用的空间很大,但是没有失真、 并且解析 BMP 图像简单。

BMP 文件的图像深度可选 lbit、 4bit、 8bit、 16bit、 24bit 以及 32bit, 典型的 BMP 图像文件由四部分组成:

①、 BMP 文件头(BMP file header),它包含 BMP 文件的格式、大小、 位图数据的偏移量等信息;

②、位图信息头(bitmap information) ,它包含位图信息头大小、 图像的尺寸、 图像大小、 位平面数、压缩方式以及颜色索引等信息;

③、调色板(color palette),这部分是可选的,如果使用索引来表示图像, 调色板就是索引与其对应颜色的映射表;

④、位图数据(bitmap data),也就是图像数据。

BMP 文件头、位图信息头、调色板和位图数据, 总结如下表所示:

数据段名称 大小(Byte) 说明
bmp 文件头 (bmp file header) 14 包含 BMP 文件的格式、大小、到位图数据的 偏移量等信息
位图信息头 (bitmap information) 通常为 40 或 56 字节 包含位图信息头大小、 图像的尺寸、图像大 小、位平面数、 压缩方式以及颜色索引等信 息;
调色板 (color palette) 由颜色索引数决定 可选,如果使用索引来表示图像的颜色, 则调 色板就是索引与其对应颜色的映射表;
位图数据 (bitmap data) 由图像尺寸决定 图像数据

一般常见的图像都是以 16 位(R、 G、 B 三种颜色分别使用 5bit、 6bit、 5bit 来表示)、 24 位(R、 G、B 三种颜色都使用 8bit 来表示) 色图像为主,我们称这样的图像为真彩色图像, 真彩色图像是不需要调色板的,即位图信息头后面紧跟的就是位图数据了。

对某些 BMP 位图文件说并非如此, 如 16 色位图、 256 色位图,它们需要使用到调色板,具体调色板如何使用,我们不关心,这里我们将会以 16 位色(RGB565) BMP 图像为例进行学习。

2. BMP图像格式

以一张 16 位 BMP 图像为例,如下图所示:

image-20241002075816002

首先在 Windows 下查看该图片的属性,如下所示:

image-20241002075835226

可以看到该图片的分辨率为 800*480,位深度为 16bit,每个像素点使用 16 位表示,也就是 RGB565。接下来使用十六进制查看工具将 image.bmp 文件打开,文件头部分的内容如下所示:

image-20241002075859486

1. bmp文件头

Windows 下为 bmp 文件头定义了如下结构体:

1
2
3
4
5
6
7
8
typedef struct tagBITMAPFILEHEADER
{
UINT16 bfType;
DWORD bfSize;
UINT16 bfReserved1;
UINT16 bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;

结构体中每一个成员说明如下:

变量名 地址偏移 大小 作用
bfType 00H 2 bytes 说明 bmp 文件的类型,可取值为: ①BM – Windows ②BA – OS/2 Bitmap Array ③CI – OS/2 Color Icon④CP – OS/2 Color Pointer ⑤IC – OS/2 Icon ⑥PT – OS/2 Pointer
bfSize 02H 4 bytes 说明该文件的大小,以字节为单位。
bfReserved1 06H 2 bytes 保留字段,必须设置为 0。
bfReserved2 08H 2 bytes 保留字段,必须设置为 0。
bfOffBits 0AH 4 bytes 说明从文件起始位置到图像数据之间的字节偏移量。 这个参数非常有用,因为位图信息头和调色板的长度 会根据不同的情况而变化,所以我们可以用这个偏移 量迅速从文件中找到图像数据的偏移地址。

bmp 文件头的大小固定为 14 个字节。 从上面的描述信息,再来对照文件数据:

image-20241002080311946

00~01H: 0x42、 0x4D 对应的 ASCII 字符分别为为 B、 M,表示这是 Windows 所支持的位图格式,该字段必须是“BM”才是 Windows 位图文件。

02~05H: 对应于文件大小, 0x000BB848=768072 字节,与 image.bmp 文件大小是相符的。

06~09H: 保留字段。

0A~0D: 0x00000046=70,即从文件头部开始到位图数据需要偏移 70 个字节。

1.2 位图信息头

同样, Windows 下为位图信息头定义了如下结构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

结构体中每一个成员说明如下 :

变量名 地址偏移 大小 作用
biSize 0EH 4 bytes 位图信息头大小。
biWidth 12H 4 bytes 图像的宽度,以像素为单位。
biHeight 16H 4 bytes 图像的高度,以像素为单位。 注意,这个值除了用于描述图像的高度之外, 它还有另外一个用途,用于指明该图像是倒向 的位图、还是正向的位图。 如果该值是一个正数,说明是倒向的位图;如果该值是一个负数,则说明是正向的位图。 一般情况下, BMP 图像都是倒向的位图,也就是该值是一个正数。
biPlanes 1AH 2 bytes 色彩平面数,该值总被设置为 1。
biBitCount 1CH 2 bytes 像素深度,指明一个像素点需要多少个 bit 数据 来描述,其值可为 1、 4、 8、 16、 24、 32
biCompression 1EH 4 bytes 说明图像数据的压缩类型,取值范围如下: ①0 – RGB 方式 ②1 – 8bpp 的 RLE 方式,只用于 8bit 位图 ③2 – 4bpp 的 RLE 方式, 只用于 4bit 位图 ④3 – Bit-fields 方式 ⑤4 – 仅用于打印机 ⑥5 – 仅用于打印机
biSizeImage 22H 4 bytes 说明图像的大小,以字节为单位,当压缩类型 为 BI_RGB 时,可设置为 0。
biXPelsPerMeter 26H 4 bytes 水平分辨率,用像素/米来表示,有符号整数。
biYPelsPerMeter 2AH 4 bytes 垂直分辨率,用像素/米来表示,有符号整数。
biClrUsed 2EH 4 bytes 说明位图实际使用的彩色表中的颜色索引数。
biClrImportant 32H 4 bytes 说明对图像显示有重要影响的颜色索引的数 目,如果是 0,则表示都重要。

从上面的描述信息,再来对照文件数据:

image-20241002080638895

0E~11H: 0x00000038=56,这说明这个位图信息头的大小为 56 个字节。

12~15H: 0x00000320=800,图像宽度为 800 个像素,与文件属性一致。

16~19H: 0x000001E0=480,图像高度为 480 个像素,与文件属性一致;这个数是一个正数,说明是一个倒向的位图,什么是正向的位图、什么是倒向的位图, 说的是图像数据的排列问题; 如果是正向的位图, 图像数据是按照图像的左上角到右下角方式排列的,水平方向从左到右,垂直方向从上到下。倒向的位图,图像数据则是按照图像的左下角到右上角方式排列的,水平方向依然从左到右,垂直方向改为从下到上。

1A~1BH: 0x0001=1,这个值总为 1。

1C~1DH: 0x0010=16,表示每个像素占 16 个 bit。

1E~21H: 0x00000003=3, bit-fileds 方式。

22~25H: 0x000BB802=768002,图像的大小,注意图像的大小并不是 BMP 文件的大小,而是图像数据的大小。

26~29H: 0x00000EC2=3778,水平分辨率为 3778 像素/米。

2A~2DH: 0x00000EC2=3778,垂直分辨率为 3778 像素/米。

2E~31H: 0x00000000=0,本位图未使用调色板。

32~35H: 0x00000000=0。

只有压缩方式选项被设置为 bit-fileds(0x3) 时, 位图信息头的大小才会等于 56 字节,否则,为 40 字节。 56 个字节相比于 40 个字节,多出了 16 个字节, 那么多出的 16 个字节数据描述了什么信息呢? 稍后再学习。

1.3 调色板

调色板是单色、 16 色、 256 色位图图像文件所持有的,如果是 16 位、 24 位以及 32 位位图文件,则 BMP文件组成部分中不包含调色板,这里就不深入了解了。

1.4 位图数据

位图数据其实就是图像的数据, 对于 24 位位图,使用 3 个字节数据来表示一个像素点的颜色,对于 16位位图,使用 2 个字节数据来表示一个像素点的颜色,同理, 32 位位图则使用 4 个字节来描述。BMP 位图分为正向的位图和倒向的位图,主要区别在于图像数据存储的排列方式, 如下如所示(左边对应的是正向位图,右边对应的则是倒向位图) :

image-20241002080754732

所以正向位图先存储图像的第一行数据,从左到右依次存放,接着存放第二行,依次这样;而倒向位图,则先存储图像的最后一行(倒数第一行)数据,也是从左到右依次存放,接着倒数二行,依次这样。

二、RGB 和 Bit-Fields

当图像中引用的色彩超过 256 种时,就需要 16bpp 或更高 bpp 的位图(24 位、 32 位)。调色板不适合bpp 较大的位图,因此 16bpp 及以上的位图都不使用调色板,不使用调色板的位图图像有两种编码格式:RGB 和 Bit-Fields(下称 BF) 。

RGB 编码格式是一种均分的思想, 使 Red、 Green、 Blue 三种颜色信息容量一样大,譬如 24bpp-RGB,它通常只有这一种编码格式,在 24bits 中,低 8 位表示 Blue 分量;中 8 为表示 Green 分量;高 8 位表示 Red分量。

而在 32bpp-RGB 中,低 24 位的编码方式与 24bpp 位图相同,最高 8 位用来表示透明度 Alpha 分量。32bpp 的位图尺寸太大,一般只有在图像处理的中间过程中使用。对于需要半透过效果的图像,更好的选择是 PNG 格式。

BF 编码格式与 RGB 不同,它利用位域操作,人为地确定 RGB 三分量所包含的信息容量。 位图信息头介绍中提及到,当压缩方式选项置为 BF 时, 位图信息头大小比平时多出 16 字节, 这 16 个字节实际上是 4个 32bit 的位域掩码, 按照先后顺序,它们分别是 R、 G、 B、 A 四个分量的位域掩码, 当然如果没有 Alpha分量,则 Alpha 掩码没有实际意义。

位域掩码的作用是指出 R、 G、 B 三种颜色信息容量的大小,分别使用多少个 bit 数据来表示,以及三种颜色分量的位置偏移量。例如对于 16 位色的 RGB565 图像,通常使用 BF 编码格式,同样这也是 BF 编码格式最著名和最普遍的应用之一, 它的 R、 G 和 B 分量的位域掩码分别是 0xF800、 0x07E0 和 0x001F,也就是 R 通道使用 2 个字节中的高 5 位表示, G 通道使用 2 个字节中的中间 6 位表示。而 B 通道则使用 2个字节中的最低 5 位表示, 如下图所示:

image-20241002080958549

三、如何得到 16 位色 RGB565 格式 BMP 图像?

在 Windows 下我们转换得到的 BMP 位图通常是 24 位色的 RGB888 格式图像,那如何得到 RGB565 格式 BMP 位图呢?当然这个方法很多,这里可以通过 Photoshop 软件来得到 RGB565格式的 BMP 位图。

首先,找一张图片,图片格式无所谓,只要Photoshop软件能打开即可;确定图片之后,我们启动Photoshop软件,并且使用 Photoshop 软件打开这张图片, 打开之后点击菜单栏中的文件→存储为,接着出现如下界面:

image-20241002081100031

在这个界面中,首先选择文件保存的路径,然后设置文件名以及文件格式,选择文件格式为 BMP 格式,之后点击保存,如下:

image-20241002081118062

点击选择 16 位色图,接着点击高级模式按钮:

image-20241002081141751

点击选择 RGB565,接着点击确定按钮即可,这样就可得到 16 位色 RGB565 格式的 BMP 图像。

四、LCD显示BMP图像实例

1. 代码编写

代码及Makefile可以看这里:LV18_LCD_DEVICE/03_lcd_show_bmp/lcd_show_bmp.c · 苏木/imx6ull-app-demo - 码云 - 开源中国 (gitee.com)

2. 开发板测试

直接在终端执行以下命令即可:

1
./app_demo image.bmp
image-20241002084850923