本文为作者原创,如需转载请在醒目位置标明原始出处,并提供可访问的超链接。
效果
实现原理
emWin的GIF显示原理是用户程序调用GUI_GIF_DrawSub()绘制函数一帧一帧的解码和显示,并且每一次GUI_GIF_DrawSub()只解码一帧画面,这就导致一些高性能的MCU在显示一些小尺寸GIF时效果都会很差。
如果开始显示之前就把整个文件全部解码完,显示的时候只显示解码完的图像,就能显著改善GIF图的显示速度,利用emWin的内存设备可以实现这个功能。
具体实现原理:
- 把整个GIF源文件加载到RAM中
- 获取GIF图的总帧数和分辨率
- 创建大小等于分辨率、数量等于总帧数的内存设备,并把GIF的每一帧都绘制到对应的内存设备中,绘制完毕后删除存放在RAM中的GIF源文件
- 将内存设备按顺序写入显存
- 如果GIF图不再使用,则删除所有内存设备
由于解码过程在绘制到内存设备的时候已经完成了,真正显示的时候就可以非常快。
源码
/**
* @brief 加载GIT图片到内存中并绘制
* @note 使用内存设备加速
* @param sFilename:需要加载的图片名,带绝对路径
* @retval 无
*/
static void ShowGIF_UseMemdev(const char *sFilename)
{
WM_HMEM hBuffMem;
WM_HMEM hMem;
GUI_MEMDEV_Handle *hMemgif;
GUI_GIF_INFO Gifinfo = {0};
GUI_GIF_IMAGE_INFO Imageinfo = {0};
/* 进入临界段 */
taskENTER_CRITICAL();
/* 打开图片 */
result = f_open(&file, sFilename, FA_READ);
if ((result != FR_OK))
{
printf("文件打开失败!\r\n");
_acbuffer[0] = '\0';
}
/* 申请一块动态内存空间 */
hBuffMem = GUI_ALLOC_AllocZero(file.fsize);
/* 转换动态内存的句柄为指针 */
_acbuffer = GUI_ALLOC_h2p(hBuffMem);
/* 读取图片数据到动态内存中 */
result = f_read(&file, _acbuffer, file.fsize, &f_num);
if (result != FR_OK)
{
printf("文件读取失败!\r\n");
}
/* 读取完毕关闭文件 */
f_close(&file);
/* 退出临界段 */
taskEXIT_CRITICAL();
/* 获取GIF文件信息 */
GUI_GIF_GetInfo(_acbuffer, file.fsize, &Gifinfo);
/* 给内存设备句柄数组分配空间 */
hMem = GUI_ALLOC_AllocZero(sizeof(GUI_MEMDEV_Handle) * Gifinfo.NumImages);
hMemgif = (GUI_MEMDEV_Handle *)GUI_ALLOC_h2p(hMem);
/* 创建与gif总帧数相同数量的内存设备,并把gif帧绘制到内存设备中 */
for(int i = 0; i < Gifinfo.NumImages; i++)
{
hMemgif[i] = GUI_MEMDEV_Create(0, 0, Gifinfo.xSize, Gifinfo.ySize);
GUI_MEMDEV_Select(hMemgif[i]);
GUI_GIF_GetImageInfo(_acbuffer, file.fsize, &Imageinfo, i);
GUI_GIF_DrawSub(_acbuffer, file.fsize, 0, 0, i);
}
/* 释放gif缓冲区 */
GUI_ALLOC_Free(hBuffMem);
/* 切换到LCD */
GUI_MEMDEV_Select(0);
/* 显示2遍GIF */
for (int j = 0; j < 2; j++)
{
/* 循环显示所有的GIF帧 */
for (int i = 0; i < Gifinfo.NumImages; i++)
{
GUI_MEMDEV_WriteAt(hMemgif[i], (LCD_GetXSize() - Gifinfo.xSize) / 2, (LCD_GetYSize() - Gifinfo.ySize) / 2);
GUI_Delay(Imageinfo.Delay * 10);
}
}
/* 删除内存设备 */
for(int i = 0;i < Gifinfo.NumImages; i++)
{
GUI_MEMDEV_Delete(hMemgif[i]);
}
/* 释放内存设备句柄数组 */
GUI_ALLOC_Free(hMem);
}
测试
平台信息
- 测试硬件: 野火 H743 Pro 开发板
- 测试软件:野火emWin例程:GIF图片显示
- 软件平台:Keil5 V5.33
测试图片参数
文件体积:6.18MB
分辨率:762*324
总帧数:101帧
帧延时:70ms
测试效果
文章开头展示的效果图就是
参考资料
- emWin V6.14 官方文档(UM03001_emWin)