[emWin]利用内存设备加速GIF图片显示——2021.03

本文为作者原创,如需转载请在醒目位置标明原始出处,并提供可访问的超链接。

效果

在这里插入图片描述

实现原理

emWin的GIF显示原理是用户程序调用GUI_GIF_DrawSub()绘制函数一帧一帧的解码和显示,并且每一次GUI_GIF_DrawSub()只解码一帧画面,这就导致一些高性能的MCU在显示一些小尺寸GIF时效果都会很差。

如果开始显示之前就把整个文件全部解码完,显示的时候只显示解码完的图像,就能显著改善GIF图的显示速度,利用emWin的内存设备可以实现这个功能。

具体实现原理:

  1. 把整个GIF源文件加载到RAM中
  2. 获取GIF图的总帧数和分辨率
  3. 创建大小等于分辨率、数量等于总帧数的内存设备,并把GIF的每一帧都绘制到对应的内存设备中,绘制完毕后删除存放在RAM中的GIF源文件
  4. 将内存设备按顺序写入显存
  5. 如果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
在这里插入图片描述
在这里插入图片描述

测试效果

文章开头展示的效果图就是
在这里插入图片描述

参考资料

  1. emWin V6.14 官方文档(UM03001_emWin)

猜你喜欢

转载自blog.csdn.net/zzz_xxj/article/details/114696404
今日推荐