硬汉嵌入式论坛

 找回密码
 立即注册
查看: 92|回复: 6
收起左侧

[emWin] GIF绘制卡顿

[复制链接]

9

主题

16

回帖

43

积分

新手上路

积分
43
发表于 4 天前 | 显示全部楼层 |阅读模式
在绘制GIF时肉眼可见的卡顿,而且刷新时还能看到从上到下的刷新,请问有没有优化的办法?

//===============================================================
void PowerOnDrawGif(void)
{  
                        if (DrawGifCount < GifInfo.NumImages)
                        {
                                GUI_GIF_GetImageInfo(_acLogo2, sizeof(_acLogo2), &ImageInfo, DrawGifCount);
                                GUI_GIF_DrawSub(_acLogo2,
                                        sizeof(_acLogo2),
                                        (LCD_X_SIZE - GifInfo.xSize) / 2,
                                        (LCD_Y_SIZE - GifInfo.ySize) / 2,
                                        DrawGifCount);
                        }
                        else
                        {
                                DrawGifCount = 0;
                        }
       
}

//===============================================================
void _cbPowerOnLogo(WM_MESSAGE * pMsg)
{
    PowerOnLogoData_t PowerOnLogoData;
        GUI_GIF_GetInfo(_acLogo2, sizeof(_acLogo2), &GifInfo);
    switch(pMsg->MsgId)
    {
        case WM_SET_FOCUS:
        {
            pMsg->Data.v = 0;
        }
        break;
        case WM_CREATE:
        {
                         // 初始化第一帧信息
            GUI_GIF_GetImageInfo(_acLogo2, sizeof(_acLogo2), &ImageInfo, 0);
            PowerOnLogoData.Tick = 0;
            //PowerOnLogoData.CurPos = 0;
            //PowerOnLogoData.LastPos = 0;
            PowerOnLogoData.hTimer = WM_CreateTimer(pMsg->hWin,TIMER_ID_LOGO_ROUND,ImageInfo.Delay * 10 / portTICK_PERIOD_MS,0);
            WM_SetUserData(pMsg->hWin,&PowerOnLogoData,sizeof(PowerOnLogoData));
                        DrawGifCount = 0;  // 重置帧计数器
        }
        break;
        case WM_DELETE:
        {
            UpdataDeviceNameToBt();
            do
            {
                __disable_irq();
                if(NULL != g_ch1SelfTest)
                {
                    g_ch1SelfTest->ExitTest();
                }
                __enable_irq();
                GUI_X_Delay(LOGO_TIMER_MS / portTICK_PERIOD_MS);
            }while(NULL != g_ch1SelfTest);
        }
        break;
        case WM_TIMER:
        {
            SelftestError_t Error;
            uint32_t PercentCur = 0;
            uint32_t TimerId;

            TimerId = WM_GetTimerId(pMsg->Data.v);
            WM_GetUserData(pMsg->hWin,&PowerOnLogoData,sizeof(PowerOnLogoData));
            if(TIMER_ID_LOGO_ROUND == TimerId)
            {
                WM_HWIN hWin;

                hWin = WM_SelectWindow(pMsg->hWin);
                WM_RestartTimer(pMsg->Data.v,ImageInfo.Delay * 15 / portTICK_PERIOD_MS);
                                PowerOnDrawGif();
                                DrawGifCount = (DrawGifCount + 1) % GifInfo.NumImages;
                                GUI_GIF_GetImageInfo(_acLogo2, sizeof(_acLogo2), &ImageInfo, DrawGifCount);
                WM_SelectWindow(hWin);
                WM_SetUserData(pMsg->hWin,&PowerOnLogoData,sizeof(PowerOnLogoData));
                break;
            }
            WM_SelectWindow(pMsg->hWin);
            WM_RestartTimer(pMsg->Data.v,LOGO_TIMER_MS / portTICK_PERIOD_MS);
            if(PowerOnLogoData.Tick < LOGO_EXIT_MS / LOGO_TIMER_MS)
            {
                PowerOnLogoData.Tick++;
            }
            Error.Error = 0;
            if(NULL != g_ch1SelfTest)
            {
                Error = g_ch1SelfTest->GetError();
            }
            if(0 != Error.Error)
            {
                GUI_RECT Rect;

                                GUI_SetFont(&GUI_DEFAULT_FONT);
                                WM_GetClientRect(&Rect);
                                GUI_SetColor(PWON_ERROR_COLOR1);
                    GUI_SetBkColor(PWON_ERROR_BKCOLOR1);
                    Rect.y1 = PWON_ERROR_INFO1_YSIZE - 1;
                                GUI_DispStringInRectFill_Buf(DEV_NAME_STRING,&Rect,GUI_TA_HCENTER | GUI_TA_VCENTER);
                                GUI_SetColor(PWON_ERROR_COLOR2);
                                GUI_SetBkColor(PWON_ERROR_BKCOLOR2);
                GetTestErrorMessage(Error,(char *)g_DispBuf,sizeof(g_DispBuf));
               
                                Rect.y0 = PWON_ERROR_INFO1_YSIZE;
                                Rect.y1 = Rect.y0 + PWON_ERROR_INFO2_YSIZE - 1;
                GUI_DrawFillRectEx(&Rect,PWON_ERROR_BKCOLOR2);
                GUI_DispStringInRect((char *)g_DispBuf,&Rect,GUI_TA_HCENTER | GUI_TA_VCENTER);
                                GUI_SetColor(PWON_ERROR_COLOR3);
                    GUI_SetBkColor(PWON_ERROR_BKCOLOR3);
                                WM_GetClientRect(&Rect);
                    Rect.y0 = PWON_ERROR_INFO1_YSIZE + PWON_ERROR_INFO2_YSIZE;
                    GUI_DispStringInRectFill_Buf(NET_ADR,&Rect,GUI_TA_RIGHT | GUI_TA_VCENTER);
                WM_DeleteTimer(pMsg->Data.v);
                WM_DeleteTimer(PowerOnLogoData.hTimer);

                SetSoundOutput(tSoundErr);
                break;
            }
            PercentCur = 0;
            if(NULL != g_ch1SelfTest)
            {
                PercentCur = g_ch1SelfTest->GetProgress();
            }
            if(PercentCur > PowerOnLogoData.Tick * (100 * LOGO_TIMER_MS / SELE_TEST_MIN_MS))
            {
                PercentCur =  PowerOnLogoData.Tick * (100 * LOGO_TIMER_MS / SELE_TEST_MIN_MS);
            }
            if(PowerOnLogoData.Percent != PercentCur)
            {
                PowerOnLogoData.Percent = PercentCur;
            }
            PowerOnLogoData.Percent = PercentCur;
            WM_SetUserData(pMsg->hWin,&PowerOnLogoData,sizeof(PowerOnLogoData));
                        if(NULL != g_ch1SelfTest)
                        {
                    if(eTest_ChkSucces != g_ch1SelfTest->GetCheckStatus())
                    {
                        break;
                    }
                        }
                        if(PowerOnLogoData.Tick < LOGO_EXIT_MS / 200)
            {
                break;
            }
                        WM_DeleteWindow(pMsg->hWin);
            g_bReDrawID = TRUE;
            g_CurPageId.Page = PAGE_DESK;
            g_CurPageId.Id = ID_DESK_CH1_V;
            TurnToFocus();
        }
        break;
                case WM_KEY:
                {
                        #if 0
            if(((WM_KEY_INFO*)(pMsg->Data.p))->PressedCnt)
            {
                if(KEY_LOK == ((WM_KEY_INFO*)(pMsg->Data.p))->Key)
                {
                                        RCC_ClearFlag();

                                        WM_DeleteWindow(pMsg->hWin);
                            g_bReDrawID = TRUE;
                            g_CurPageId.Page = PAGE_DESK;
                            g_CurPageId.Id = ID_DESK_SHOWALL;
                            TurnToFocus();
                }
            }
            #endif
                }
                break;
        case WM_PAINT:
        {
            GUI_RECT Rect;
                       
            WM_GetClientRect(&Rect);
            GUI_DrawFillRectEx(&Rect,GUI_BLACK);
            WM_GetUserData(pMsg->hWin,&PowerOnLogoData,sizeof(PowerOnLogoData));
            PowerOnDrawGif();
        }
        break;
        default:
        {
            WM_DefaultProc(pMsg);
        }
        break;
    }
}



回复

使用道具 举报

5

主题

278

回帖

293

积分

高级会员

积分
293
发表于 3 天前 | 显示全部楼层
gif分辨率多少?要是比较高的话边读取边解码是会比较慢的
如果gif的分辨率不高,总帧数量很少,且emwin可用内存空间够装下整个解码后的gif,那可以在显示前先把所有帧解码进memdev里,按一帧一个memdv这样子,然后根据gif的帧间隔去显示刷这些memdev,这样就很流畅了
回复

使用道具 举报

5

主题

278

回帖

293

积分

高级会员

积分
293
发表于 3 天前 | 显示全部楼层
或者也可以大概测一下读取+刷新的时间,如果大于gif的帧间隔时间,可以把帧间的延时函数删掉,用读取+刷新的时间代替帧间延时
回复

使用道具 举报

9

主题

16

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 3 天前 | 显示全部楼层
DX3906 发表于 2025-8-15 09:18
gif分辨率多少?要是比较高的话边读取边解码是会比较慢的
如果gif的分辨率不高,总帧数量很少,且emwin可 ...

你好,gif分辨率是240×207,还没使用过memdev,使用的话是不是要占用额外的内存?内存本来就快满了,gif数据大概是37KB,总内存才64KB
回复

使用道具 举报

5

主题

278

回帖

293

积分

高级会员

积分
293
发表于 3 天前 | 显示全部楼层
YISHUI 发表于 2025-8-15 10:06
你好,gif分辨率是240×207,还没使用过memdev,使用的话是不是要占用额外的内存?内存本来就快满了,gif数 ...

是的,这内存不够用memdev,可以试试我在上一楼说的方法,用读取+显示消耗的时间代替原本的帧间延时
或者如果你外部存储空间够的话,也可以试试先把gif转成位图序列再保存,直接显示位图序列能省掉解码时间
回复

使用道具 举报

9

主题

16

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 3 天前 | 显示全部楼层
DX3906 发表于 2025-8-15 10:43
是的,这内存不够用memdev,可以试试我在上一楼说的方法,用读取+显示消耗的时间代替原本的帧间延时
或 ...

Flash应该是够用的,总共有512KB,目前用了有370KB这样,gif转成位图是用BmpCvt像转位图那样转成.c文件转吗?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117586
QQ
发表于 前天 09:29 | 显示全部楼层
参考我此贴的图片浏览功能,非常到存储设备刷新,就是不知道你的动态内存够大不

https://forum.anfulai.cn/forum.php?mod=viewthread&tid=17330
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-18 01:19 , Processed in 0.039702 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表