stm32 基于TouchGFX显示视频动画的详细制作过程和讲解

stm32 使用TouchGFX显示太空人动画详细制作过程

1.素材处理

使用软件:格式工厂、Matlab

首先准备好太空人的git或者太空人的mp4。

用格式工厂改成自己需要的分辨率。

image-20220117161908744

然后在采用下面的代码用Matlab来逐帧采集图片,其实还有很多别的方法,但是opencv电脑没装,就不想麻烦了。

代码中的路径按需更改

% % fig --> jpg
% r = 'H:\PersonalProducts\astronaut\human.gif';
% info = imfinfo(r);%第一次读取,用于获取属性值
% W = info.Width;
% H = info.Height;
% W = W(1);
% H = H(1);
% len = length(info);%总帧数
% for i = 1 : len   %截取每一帧
%     [Ii, map] = imread(r, 'frames', i);  %将第i帧保存为索引格式
%     I2 =ind2rgb(Ii,map);   %最关键的,将索引转为RGB格式!
%     imwrite(I2,strcat('H:\PersonalProducts\astronaut\output\astronaut_',num2str(i,'%02d'),'.','png'));
% end

% mp4 --> jpg
apple='H:\PersonalProducts\astronaut\astronaut.mp4';
obj = VideoReader(apple);
for i=1 : 60 %视频3秒,每秒30帧
    astronaut = read(obj,i);
    imwrite(astronaut,strcat('H:\PersonalProducts\astronaut\output\',num2str(i,'%02d'),'.','png'));
end

2.Touchgfx移植

这里就不做讲解了,每个人板子不一样,配置不同。

可以参考这个大佬的移植,非常详细。

参考链接

3.使用控件animated image

先把之前处理的好的会错增加到资源里

image-20220117164237289

image-20220117162217819

image-20220117162235903

这里的意思是开始图片和最后一张图片,还有更新间隔,我们测试的话先打开自动加载选项。

**注意:**它不是在第一和第二张照片之间切换,而是从第一张持续到最后一张,但是图片资源的命名要按照固定格式来。比如: name_01.png -----------> name_xx.png

4.仿真和烧录看效果

没有拍gif动图,其实已经是可以动的了。

资源的话,内部Flash是绝对不够的,可以采用QSPI映射内存地址的方法,也可以采用从sd卡读取图片资源的方法(这个后期我有时间会写个文章),这里采用QSPI的方法,这个方法有制作好的算法才行,如果是自己制作的板子可以到官方找例程来改生成FLM烧录算法,如果是网上的板子,找店家要就行了。

image-20220117162635854

image-20220117162658420

5.增加启动和暂停控制

TouchGFX采用的是MPV架构,界面和底层完全分离,对于复杂的UI界面非常友好,下面的例子是基于屏幕到底层的例子,View–>Presenter–>Model。其实如果只是控制动画的变化,是只用view自己就够了,但是这样就不能通知到底层。

image-20220117163150615

得先把空间自己装载先给关了。

再增加回调虚函数

生成代码后,打开头文件即可看到创建的回调函数。

image-20220117182019278

image-20220117183457624

image-20220117181743242

然后我们在screenview.cpp里重写并实现这个函数。

image-20220117192606101

void screenView::StartAnimation()
{
    if(toggleButton1.getState()){
        animatedImage1.startAnimation(false, true, true);   //不反转,重置,循环
    }else {
        animatedImage1.stopAnimation();//停止动画
    }
    animatedImage1.invalidate();    //重绘控件,必须调用
    
    presenter->button1Clicked(toggleButton1.getState());    //需在presenter定义,通知presenter,按键按下。
}

如果不需要通知底层,那把最后一行删掉,也就成功了。

hpp中增加定义,在cpp里定义。

image-20220117192814221

image-20220117192907511

void screenPresenter::button1Clicked(bool  state)
{
    model->viewBtnClick(state);//通知model
}

然后再在model里同样的做法。

image-20220117193021883

image-20220117193054082

void Model::viewBtnClick(bool  state)
{

    if(state){
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_RESET);
    }else {
        HAL_GPIO_WritePin(GPIOH, GPIO_PIN_7, GPIO_PIN_SET);
    }

}

**注意:**我这里包含了main.h,用的cubemx生成的会有extern {}的那个,如果是自己弄的要注意,c和c++一起的时候要这样弄,不然编译错误。

以上基本就算是成功了,MPV的用法也走了一遍,下面讲讲为什么可以这么玩。

image-20220117193757882

在view收到用户的交互事件的时候,不能直接和model通信,只能通过presenter,但是怎么通过presenter呢,其实在设计的时候这个view底层就已经做好了,在view里是有一个对应的screen的presenter的指针。

image-20220117191352312

同样在presenter里也有一个model的指针,下面给指针地方的截图,modellistener是moder的父类。同时这个bind也会绑定对应一个的model。

image-20220117191352312

单个screen界面的时候就是这样多个prensenter和多个view对应一个model,当创建多个screen节目的时候那就是多个了,每个都是对应自己的mpv关系。

如果是简单界面相比于lvgl可能有点麻烦了,但是当复杂界面的时候优势就非常明显了,各个界面显示分层,还可以进行各个对应的单元测试等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炒饭多加个蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值