PNG(Portable Network Graphics)格式,是一种光栅图形文件格式,支持无损数据压缩和透明度, 支持基于调色板的图像、灰度图像以及非调色板的全色RGB图像。1999年,Unisys公司进一步中止了对自由软件和非商用软件开发者的GIF专利免费许可, 从而使PNG格式获得了更多的关注。PNG是目前保证最不失真的格式,采用LZ77算法的派生算法进行压缩, 能把图像文件压缩到极限以利于网络传输,但又能保留所有与图像品质有关的信息。
34.1. 移植PNG库
emWin对PNG支持可以通过使用基于Glenn Randers-Pehrson, Guy Eric Schalnat和Andreas Dilger的“libpng”库来实现。 但emWin内部并不包含PNG解码库,需要用户自行移植。
接下来我们讲解一下将PNG库移植到emWin工程中的步骤。
-
下载并解压emWin_png压缩包。PNG解码库可以从emWin官网下载到, 链接如下:https://www.segger.com/downloads/emwin/emWin_PNG。下载完成后解压得到的emWin_png压缩包, 可以看到如图 emWin_png压缩包内容 所示的结构,压缩包内包含了对应emWin各个版本的PNG解码库, 我们选取适合我们例程的版本即选择V544。
-
添加PNG库到工程文件夹。选择好版本之后,将PNG库整个文件夹复制到工程文件夹下,其实随便那个文件夹都行, 只要在工程文件夹内。如图 添加PNG库到工程 所示,我们选择将PNG库放在工程的STemWin文件夹下,并重命名为png;
-
添加PNG库文件到工程。在MDK工程内新建分组并把PNG库添加进新分组中, 如图 添加PNG库文件到工程 所示;
-
添加PNG库头文件路径。最后一步,在工程设置中把PNG库的头文件路径添加进去, 见图 添加PNG库头文件路径 。
至此,emWin的PNG移植就完成了,可能最后工程编译完成后有较多警告,属于正常情况。
此PNG库在做解码操作的时候会固定占用21KB的RAM空间,这部分与图像大小无关,而总的RAM占用可通过下面的公式得到:
总RAM占用 = (图像xSize + 1)* 图像ySize + 21KB
34.2. PNG显示相关API
34.2.1. GUI_PNG_Draw()
在当前窗口的指定位置绘制一个已加载到内存中的png文件。
代码清单:PNG-1 函数原型
int GUI_PNG_Draw(const void *pFileData, int FileSize, int x0, int y0);
-
pFileData: 指向png文件所在的存储区域的开头的指针;
-
DataSize: png文件的字节数;
-
x0: png左上角在屏幕上的x位置;
-
y0: png左上角在屏幕上的y位置。
返回值:绘制成功返回0,绘制失败返回非0。不过当前的实现是任何情况都返回0。
34.2.2. GUI_PNG_DrawEx()
在当前窗口的指定位置绘制一个png文件,该文件不必加载到内存中。
代码清单:PNG-2 函数原型
int GUI_PNG_DrawEx(GUI_GET_DATA_FUNC *pfGetData, void *p, int x0, int y0);
-
pfGetData: 指向为获取数据而调用的函数的指针;
-
p: 传递给pfGetData指向的函数的空指针;
-
x0: png左上角在屏幕上的x位置;
-
y0: png左上角在屏幕上的y位置。
返回值:绘制成功返回0,绘制失败返回非0。不过当前的实现是任何情况都返回0
需要注意的是,PNG解码库会在其内部为整个图像分配一个缓冲区,这是此函数无法避免的。
34.3. PNG图片显示实验
接下来我们通过一个实验来讲解如何简单的显示PNG图片,更多API函数的演示实验可参考官方例程2DGL_DrawPNG.c,例程路径如下:
SeggerEval_WIN32_MSVC_MinGW_GUI_V548\Sample\Tutorial\2DGL_DrawPNG.c
34.3.1. 代码分析
34.3.1.1. 绘制外部存储器(SD卡)中的PNG
代码清单:PNG-3 _ShowPNGEx函数(MainTask.c文件)
/**
* @brief 直接从存储器中绘制PNG图片数据
* @note 无
* @param sFilename:需要加载的图片名
* @retval 无
*/
static void ShowPNGEx(const char *sFilename, int x0