OpenHarmony轻松玩转GIF数据渲染 精华
OpenAtom OpenHarmony(以下简称“OpenHarmony”)提供了Image组件支持GIF动图的播放,但是缺乏扩展能力,不支持播放控制等。今天介绍一款三方库——ohos-gif-drawable三方组件,带大家一起玩转GIF的数据渲染,搞定GIF动图的各种需求。
效果演示
本文将从5个小节来带领大家使用ohos-gif-drawable这一款三方库,其中1、2、3这3个小节,主要介绍了ohos-gif-drawable的核心能力、GIF软解码和GIF绘制。4和5小节主要是扩展讨论,如何添加滤镜效果和软解码遇到的耗时问题。
1.GIF的文件格式理论基础
工欲善其事必先利其器。首先我们需要为自己打下理论基础。了解GIF的数据格式,为后续解码GIF提供理论支持。
通过学习GIF的文件格式,我们对于GIF的组成格式有了一定的了解,并且有助于理解后面GIF的解码。
在开始介绍之前,我想让大家了解一下整体的结构思路如下图:
其中gifuct-js三方库主要完成了解码的工作。
ohos-gif-drawable三方库则是在gifuct-js的三方库之上,进行了封装。并结合了OpenHarmony的Canvas绘制能力,达到了播放和控制GIF的能力。
2.GIF软解码:gifuct-js三方库介绍
GIF解码我们使用了gifuct-js这个库,它是一个纯JavaScript的GIF解码库。首先我们需要了解基础用法。
2.1 参考样例将一个文件ArrayBuffer转换为GIF解码后的帧数据数组。
2.2 由于OpenHarmony的Image生成PixelMap需要的数据是BGRA数据,而2.1生成的frames所有数组中的patch字段则是RGBA数据,所以我们需要使用
然后将frame目前还未生成的patch字段数据,通过generatePatch 函数,将RGBA的数据更换为BGRA即可,如下代码所示:
generatePatch函数,在这里会根据颜色表colorTable和基于颜色表的图像数据pixels以及透明度transparentIndex生成BGRA格式的patchData,这个数据和Canvas中getImageData获取的ImageData数据是一致的,都是Uint8ClampedArray类型,可以直接使用putImageData让canvas绘制。
最后,生成的patchData赋值给Frame的patch字段。
这里我们并没有直接使用Canvas的putImageData直接绘制。为了提升扩展性,我们使用了Image的能力来生成PixelMap,这样处理为后续滤镜效果提供了可能,也方便后续绘制流程。
好了,到这里我们就基本上把gifuct-js库的基础使用简单介绍完了。
如何使用GIF:ohos-gif-drawable三方库的介绍。
我们先来看看整个ohos-gif-drawable组件的模型图,通过模型图,我们可以看到,用户只要关注GIFComponent组件,和GIFComponent.ControllerOptions配置参数以及控制参数autoPlay和resetGif即可,非常简单!
1. 支持的功能列表如下
● 支持播放GIF图片。
● 支持控制GIF播放/暂停。
● 支持重置GIF播放动画。
● 支持调节GIF播放速率。
● 支持监听GIF所有帧显示完成后的回调。
● 支持设置显示大小。
● 支持7种不同的展示类型。
● 支持设置显示区域背景颜色。
2. 如何使用ohos-gif-drawable
首先需要使用npm下载ohos-gif-drawable三方库
接下来我们需要配置一个worker给gifuct-js解码使用。
配置worker,在应用工程的entry/src/main/ets/pages目录下新建workers文件夹,并且创建文件 gifParseWorker.ts ,文件内容如下:
然后在entry目录的build-profile.json5文件中,添加如下内容:
到这里我们worker就配置好了。
下面就到了正式使用环节,我们只要在UI界面需要的地方写上自定义控件GIFComponent,然后传入GIFComponent.ControllerOptions,gifAutoPlay,gifReset这三个参数就能控制gif动画。
举个简单的例子说明一下
这里ResourceLoader内置了加载网络资源GIF,本地工程资源GIF和本地路径资源GIF文件数据的能力。
如果你已经有了GIF文件的arraybuffer数据,也可以直接调用modelx.loadBuffer(buffer: ArrayBuffer, readyRender: (err?) => void, worker: any)进行GIF播放。
甚至你已经生成了GIF解析数据,比如调用了2.2中的解码代码,那么你也可以直接调用modelx.setFrames(images?: GIFFrame[])来进行gif播放。
1.控制GIF的播放与暂停:
组件内部会监听该参数的变化,用户只要改变值即可达到控制效果
2. 重置GIF的播放
由于重置不需要状态管理,所以组件内监听到数据变化就会重置gif播放
3. 设置GIF动画播放速度
调用setSpeedFactor(speed: number)即可调整播放速度speed 为对比原始速率的乘积因子,比如设置0.5即为原始速率的0.5倍,设置为2即为原始速率的2倍。
4. 监听GIF动画播放回调(比如第一次动画结束)和获取动画实际播放总时长
调用setLoopFinish(fn: (loopTime?) => void)可以通过回调得到GIF动画运行一周期耗时和一周期结束时间节点。
5. 显示GIF任意一帧
调用setSeekTo(gifPosition: number)可以直接展示该gif的某一帧图像。
到这里ohos-gif-drawable三方库的主要能力都介绍完了,是不是很简单呢!
6. 适配组件的大小
modelx.setScaleType(ScaleType.FIT_CENTER) // 将图像缩放适配组件大小调用setScaleType(scaletype: ScaleType)可以将图像和组件大小进行适配。
目前支持的类型如下图所示:
GIFComponent.ScaleType
为什么要配置worker
在具体实践过程中我们会发现,当我们按下解码按钮的时候,主界面会有一点卡顿的情况。特别是大的GIF文件进行解码的时候效果更明显。这是因为我们在主线程中进行了CPU的密集型计算,这是一个耗时且占用CPU的操作。主线程中是不能执行耗时操作的。但是JavaScript只有一个线程啊?那么解码这一块操作该如何处理会比较好呢?带着疑惑,我去查阅了资料发现JavaScript虽然属于单线程环境。但是通过引入Worker的能力,引入子线程worker,可以实现JavaScript的“多线程”技术。
OpenHarmony如何在子线程中处理耗时任务
为了争取良好的用户体验,我们需要将耗时操作封装至子线程中。
这里简单描述一下worker的能力:
能够让主页面运行的JavaScript线程中加载运行另外单独的一个或者多个JavaScript线程,但是它的多线程编程能力区别于传统意义上的多线程编程。主线程和Worker线程之间,不会共享任何作用域和资源,他们的通信方式是基于事件监听机制的 message。
接下来我们参考OpenHarmony文档下的worker能力
1. OpenHarmony环境下Worker的API接口列表
2. Worker的使用简单案例
经过了解之后,我们可以把解码的耗时封装到worker中处理,避免主线程耗时操作占用CPU导致卡顿问题。提升用户体验。
这也是使用ohos-gif-drawable三方库需要配置worker的原因。
扩展部分
GIF的滤镜效果
1. 灰白滤镜
2. 反转滤镜
3. 高级滤镜效果
假设我们这边已经拿到了patch: Uint8ClampedArray像素数据,这里我需要先将其变换为一张PixelMap数据,参考GIFComponent中patch数据转换为PixelMap的代码。
4. 高斯模糊
然后对PixelMap像素数据进行高斯模糊, 调用 `blur(pixelmap,10,true, (outPixelMap)=>{ // 模糊后的pixelmap数据})`在回调中获取模糊后的pixelmap。以下是模糊处理的算法:
如果需要高级滤镜效果可以参考ImageKnife组件的transform部分,这里仅仅展示模糊效果。
由于滤镜效果目前ohos-gif-drawable三方库并没有开发接口提供出来,所以开发者可以根据实际需求重写自定义组件GIFComponent.,只需要在生成PixelMap的代码片段中加入滤镜代码,即可利用滤镜效果开发更多精彩的应用。
参考资料
1.《GIF文件格式解析》
https://segmentfault.com/a/1190000022866045
2.GIF解码库gifuct-js
https://github.com/matt-way/gifuct-js
3.GIF解码库底层逻辑jsBinarySchemaParser
https://github.com/matt-way/jsBinarySchemaParser
4.高级滤镜算法借鉴
5.OpenHarmony环境下Worker的API接口列表
6.Worker的使用简单案例
https://gitee.com/wang_zhaoyong/js_worker_module/wikis/Worker%E7%AE%80%E5%8D%95%E4%BD%BF%E7%94%A8
7.Web Worker API参考
https://developer.mozilla.org/zh-CN/docs/Web/API/Worker
8.OpenHarmony的Canvas文档
9.OpenHarmony的CanvasRenderingContext2D对象文档
Canvas功能还是强大
GIF编辑组件,很实用的工具
这配置GIF的功能真厉害
PC上有类似的软件吗?