今天聊到动图,它们在 App 上都很常见,如聊天的表情,直播的送礼 & 座驾特效,H5 上的活动图,视频的录制等等。而动图有很多种格式,常用的 帧动画、Gif、WebP、Apng、Svga。由于最近项目加入 Svga,因此顺便学习下其他动图,也把之前记录的 LivePhoto 一起总结进来,做一次复习。
本篇可以说是一篇播放 & 制作的合集。大家将会看到 YYImage,Svga-Player,iSparta 转换等开源库 & 工具。而主要说明的动图格式是 Gif、WebP、Svga、LivePhoto。除了 LivePhoto,其它动图的的播放在 iOS 端的大概流程都是通过 ImageIO 绘制出 UImage,再通过 CADisplayer 进行逐帧播放,只是解码库不同,如 WebP 是依靠 Google 提供的库(因为编码不一样)。也正由于他们是逐帧播放的,所以可以将每帧数据解码后再重新编码成其他格式的动态。最为关键的还是编码上,从而形成各自的优势,就目前项目的动图还是比较多使用 WebP,而 Svga 目前使用上似乎更好,特别是在直播的大礼物特效上。
使用记录
时间点 | 原因 | 结果 |
---|---|---|
1 | App 按钮太素 | 加入 png 来显示按钮 |
2 | 静态图片看厌了 | 将 pngs 连续播放 |
3 | 多端无法共用 | 使用 Gif |
4 | 有锯齿,且体积很大 | 换成 WebP |
5 | 动图体积得再小 | 换成 Svga |
6 |
前文
可以先通过 YYImage 作者 ibireme 博文的前半部分来了解 图片历史后,接着阅读本章后续内容,最后再回来看后半部分的知识点。
本篇 Demo:
正文
动图都是播放帧图片,即解码出来的一张张图片就是需要播放的,因此它们的关键数据就是 Image & Duration,
一般的图片在播放过程都经历: 解码 -> 绘制
YYImage
YYImage 使用了 CADisplayLink & NSOperationQueue 来进行动画的逐帧绘制。它也几乎支持列出的大部分动图格式的播放。其中除了 WebP & APNG 两个,其余支持的图片格式都使用了 ImageIO 来进行解码。
参考
GIF
1 | // 从 gif 里解码出单张 image |
制作 Gif 的函数可以查看 chenqihui/QHAnimationImageDemo
参考
APNG
由于项目并没有使用,所以 Demo 没有添加,但在 YYImage 源码里可以看到通过
1 | static uint8_t *yy_png_copy_frame_data_at_index(const uint8_t *data, |
获取 bytes 之后,再有 ImageIO 转为 UIImage,也就是说上述函数是完整的 APNG 解码过程了。
WebP
1 | WEBP_EXTERN(int) WebPDemuxGetFrame( |
通过 WebP 库将数据解码出来,最后也是通过 CGImageCreate 来生成 UIImage。
调用 WebP 库的方法可以参考 YYImageCoder ,或者搜索一下,如 iOS-WebP/UIImage+WebP.m ,原理是一样的。
参考:
Svga
SVGA 是一种动画格式
SVGA 类似于 Dragonbones / CreateJS
调用来的 绘制:SVGAPlayer & 解码:SVGAParser
集成它的时候,搜索下估计都会看到这两篇
它的制作不是序列帧,而是将动画切割一个个小图片,然后对其进行独立播放,类似游戏开发:保存各部分切图组成的纹理集和动画数据,只需要极少的原画,便可完成千变万化的动作动画组合。
下面就是 Svga 使用的对象 SVGAVideoEntity,其中 images & sprites,对应的就是 图片元素 & 动画数据。
1 | @interface SVGAVideoEntity : NSObject |
由于这样的模式,它提供了可以替换某一图片元素的 API,这也方便在动图中通过占位图片,来加入其它自定义的图片元素。相比其它动图需要多帧获取 & 替换才能达到的效果,其确实更方便。
LivePhoto
Live Photo 是由一段3秒的视频 + 一张图片构成的。
原生 LivePhoto 视频采集的时间区间是由 按键后1.5s + 按键前1.5s 构成的。[-1.5s ~ 0s, 拍摄瞬间,0s ~ 1.5s]。
复制代码最后合成 LivePhoto 展示的照片,取得是相机采集后 3s 片段中的中央那一帧。
Demo 采用 Mov 转换 LivePhoto 的方式,这也是目前 短视频App 生成 LivePhoto 壁纸的方式。它的播放器使用的是 PHLivePhoto,同时保存在相册就可以做为手机的壁纸,详细请查看 chenqihui/QHAnimationImageDemo,里面保存相册的代码注释了。
纸上电影
它的制作可以看看接下来的视频(杨超越喔,哈哈),只需一张图片 + 屏幕片,然后按方向拖动 屏幕片 即可出现动画。它算是模拟了屏幕的成像,跟走马灯其实是一样的,只是它采用一张原图,通过栅栏图片的遮罩显示不同的图片位置。至于在 iOS 实现,目前还在研究ing。
参考:
转换
pngs 转 GIF、Apng、WebP 工具
转换在参考文中都十分详细,大部分测试也是有用的,因此直接查看即可。
参考:
PC 制作 WebP
先下载 libwebp,里面提供 .a & .h外,还提供 bin,这样即可新建项目使用,也可以命令使用,这里讲讲使用 bin。
环境变量配置 & PATH
1、配置单用户全局变量(重启后配置失效)
1 | // /Users/用户名(e.g.chen)/.bash_profile |
2、全局配置(永久有效)
1 | // /etc/profile |
pngs2webp
1、单张转 无动画webp,再合并成 动画webp
- cwebp
- webpmux
2、看 iSparta 里面是先壮 apng,再转 webp
- 1、pngs2apng
- 2、apng2webp
3、Google 提供了将多张图片转为 webp,并且多张图片格式可以不同
- img2webp
参考:
除了以上三种常用的步骤,当然还有其他,如先 GIF,再 webP。
总结
以上的动图都有各自的优缺点,按需使用。WebP 是使用了视频的 VP8 编码格式。而 Svga 采用的方式在 体积 & 解码 上从理论与实际使用看都更好,越大的图会越明显。Svga 不仅对文件进行 protobuf % zlib 的压缩, 关键还在 PC 工具上,将 设计师 的动画原型转出 Svga 需要的 Bitmap & Frame, 这种类似游戏的动画模式资源,可以说很 cool 哈。当然看完其实也发现,除了 Svga,其他格式是可以在 iOS 端进行相互转换,这也是常常在客户端看到的 录制 Gif、截屏、录屏、制作 LivePhoto 壁纸、使用 WebP 也可以在客户端制作等等。
TODO