emWin支持BMP图片的显示,提供的API函数主要支持两种图片显示方式:一种是从外部存储器中读取数据并显示, 一边读一边显示,占用RAM空间小,但显示速度很慢;另一种是从外部存储器把图片数据全部读取出来再显示,显示速度较快,但占用大量RAM空间。
emWin支持BMP文件格式版本3,它包含几种不同的图像格式,如表格 emWin支持的BMP格式 所示:
31.1. BMP图片格式
BMP文件格式,又称为位图(Bitmap)或是DIB(Device-Independent Device,设备无关位图), 是Windows系统中广泛使用的图像文件格式。BMP文件保存了一幅图像中所有的像素。
BMP格式可以保存单色位图、16色或256色索引模式像素图、24位真彩色图象, 每种模式中单一像素点的大小分别为1/8字节,1/2字节,1字节和32字节。目前最常见的是256位色BMP和24位色BMP。
BMP文件格式还定义了像素保存的几种方法,包括不压缩、RLE压缩等。常见的BMP文件大多是不压缩的。
BMP文件的数据可以分为四个部分:
-
BMP文件头: 存放了有关文件的格式、大小等信息。我们仅讨论24位色不压缩的BMP,所以文件头中的信息基本不需要注意;
-
位图信息头: 包括图像大小、位平面数、压缩方式、颜色索引等信息。在位图信息头之中,只有“大小”这一项对我们比较有用。 图像的宽度和高度都是一个32位整数,在文件中的地址分别为0x0012和0x0016。
-
调色板: 索引与其对应的颜色的映射表。16色或256色BMP有颜色表,但在24位色BMP文件则没有,我们这里不考虑。
-
位图数据: 实际的像素数据。
因此总的来说BMP图片的优点是简单。下面我们使用WinHex软件(跟UltraEdit软件功能类似)来分析一下BMP图像的文件内容。
31.1.1. BMP文件头
图 BMP文件头部信息 的阴影部分处是某张BMP图片文件的头部信息,具体说明参考表格 BMP文件头说明 。
3到14字节的意义可以用一个结构体来描述,见 代码清单:BMP-1 。
代码清单:BMP-1 BMP文件信息数据结构体
typedef struct tagBITMAPFILEHEADER
{
//attention: sizeof(DWORD)=4 sizeof(WORD)=2
DWORD bfSize; //文件大小
WORD bfReserved1; //保留字,不考虑
WORD bfReserved2; //保留字,同上
DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和
} BITMAPFILEHEADER,tagBITMAPFILEHEADER;
31.1.2. 位图信息头
剩下的部分就是位图信息头,也就是 图位图信息头 的处,具体说明参考 表位图信息头 。
位图信息头结构体,见代码清单:BMP-2。
代码清单:BMP-2 位图信息头内容
typedef struct tagBITMAPINFOHEADER
{
//attention: sizeof(DWORD)=4 sizeof(WORD)=2
DWORD biSize; //指定此结构体的长度,为40
LONG biWidth; //位图宽,说明本图的宽度,以像素为单位
LONG biHeight; //位图高,指明本图的高度,像素为单位
WORD biPlanes; //平面数,为1
WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24新的可以是32
DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩
DWORD biSizeImage; //实际位图数据占用的字节数
LONG biXPelsPerMeter; //X方向分辨率
LONG biYPelsPerMeter; //Y方向分辨率
DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的
} BITMAPINFOHEADER,tagBITMAPINFOHEADER;
由于使用的是24位的位图,所以没有调色板,位图的大小为768*432。
31.1.3. 图像像素数据
本节使用色彩深度为24位真彩色的BMP图片进行讲解,则54字节之后就是像素部分,如图 BMP像素数据 的阴影部分③处。
以上内容就是对BMP图像文件的介绍。如果想要了解其中更多的细节,可以上网搜索相关的内容。
31.2. BMP显示相关API
31.2.1. GUI_BMP_Draw()
在当前窗口中的指定位置绘制一个已加载到内存中的bmp文件。
代码清单:BMP-3 函数原型.
int GUI_BMP_Draw(const void *pFileData, int x0, int y0);
pFileData:指向bmp文件所在的内存区域起始地址的指针;
x0:位图左上角在屏幕上的x位置;
y0:位图左上角在屏幕上的y位置。
返回值:绘制成功返回0,绘制失败返回非0。
31.2.2. GUI_BMP_DrawEx()
在当前窗口的指定位置绘制不需要加载到内存中的bmp文件。
代码清单:BMP-4 函数原型
int GUI_BMP_DrawEx(GUI_GET_DATA_FUNC *pfGetData, void *p, int x0, int y0);
-
pfGetData: 指向用于获取数据的函数的指针;
-
p: 传递给pfGetData指向的函数的空指针;
-
x0: 位图左上角在屏幕上的x位置;
-
y0: 位图左上角在屏幕上的y位置。
返回值:绘制成功返回0,绘制失败返回非0。
31.3. BMP图片显示实验
接下来我们通过一个实验来讲解如何简单的显示一张BMP图片,更多API函数的演示实验可参考官方例程2DGL_DrawBMP.c,例程路径如下:
SeggerEval_WIN32_MSVC_MinGW_GUI_V548\Sample\Tutorial\2DGL_DrawBMP.c
31.3.1. 代码分析
31.3.1.1. 绘制外部存储器(SD卡)中的BMP
代码清单:BMP-5 ShowBMPEx函数(MainTask.c文件)
/**
* @brief 直接从外部存储器中绘制BMP图片
* @note 无
* @param sFilename:需要加载的图片名
* x0:图片左上角在屏幕上的横坐标
* y0:图片左上角在屏幕上的纵坐标
* @retval 无
*/
static void ShowBMPEx(const char *sFilename, int x0, int y0