1
matrix67 2014-12-04 22:55:51 +08:00 via Android
因为好像是因为费电
|
2
jox OP @matrix67 额,对,gif会导致cpu和gpu不停地工作,确实会费电。。。。我在考虑要不要也学别人只渲染第一帧意思意思得了。。。
|
3
vixvix 2014-12-04 23:04:41 +08:00
狗了下, Flipboard有篇文章和源码,也许对你有用:
http://engineering.flipboard.com/2014/05/animated-gif/ |
4
gluttony 2014-12-04 23:22:36 +08:00 via iPhone
我以前试过各种gif解码库,都没有把图片下载到本地后套个静态HTML模版用UIWebView展示高效和省资源(很多段子应用都用的这个方法)。不过那时Flipboard的库还没出,你可以和UIWebView对比下。
|
5
jox OP @vixvix 嘿,我也刚刚找到了这篇文章,我下载下来了源码看了一下,他们是使用的CADisplayLink,然后手动渲染layer的内容,这样就可以不必重复解码了,我还不太清楚CADisplayLink怎么用,这个应该是我需要的,不过同样非常感谢
|
6
jox OP @gluttony UIWebView不行,不可能每个tablecell里都加载个UIWebView,最开始我就用过web view,效果不满意,而且有一些问题绕不过去,其实只要修改每帧的尺寸即使一下载入好几十帧也不怎么占内存,但是想要丝般顺滑,必须要跳过重复解码的过程。flipboard的方法应该能够解决我的问题,我需要好好研究一下他们的源代码
|
7
Smartype 2014-12-05 17:07:32 +08:00
@jox 其实没有你想得那么复杂的。就是把所有的帧都解出来,然后主动绘制。什么叫做主动绘制呢?就是像游戏一样,使用cadisplaylink让系统通知你绘制。
话说滚动的时候os会停止uiimageview的绘制来保证滚动的流畅性吧?这是你说的抽么? |
8
jox OP @Smartype flipboard的做法就是使用CADisplayLink的,他们的做法是在需要刷新的时候直接使用解压缩过的图片来设置layer的contents属性。所以可以提前强制解压,或者只在第一次渲染的时候解压缩,后续的渲染保证流畅。
如果使用UIImageVIew来渲染的话,使用UIImage的-(UIImage *)animatedImageWithImages:(NSArray *)images duration:(NSTimeInterval)duration 来创建gif,然后直接set UIImageVIew的image属性也可以渲染gif,我不清楚UIImageView是怎么实现的,但是这么做的话的确会导致卡顿,因为UIImageView的animationImages的属性是copy,所以我猜测内部实现是使用的CAKeyframeAnimation,CAKeyframeAnimation来实现gif的话就是要把每一帧都copy过去,Image I/O要想直接使用解压缩过的数据似乎得保留UIImage指针,这个应该很容易就能测试出来,copy的话就不是之前的指针了,于是就又解压缩了一次,这个是在主线程发生的,否则无法解释卡顿现象啊。 |
9
Smartype 2014-12-07 14:10:46 +08:00
@jox 我的意思是拖动的时候应该是挂起了runloop中的timer。导致卡顿的不是复制或者解码这些操作。
和uikit不同,cadisplaylink是用来做游戏的,是要在拖动的时候渲染的。这是我的理解。 如果是你认为是资源不足的原因的话,可以用一个小得可怜的gif试试。看拖动的时候是不是不会渲染。 |
10
jox OP @Smartype 今天我拿Instruments测试了一下,证明我之前的猜测是错误的,你说的没错,导致卡顿的原因不是因为解码,我用一个超大的gif,然后使用同一个UIImage来创建UIImageView,然后加到当前view的hierarchy里,只有第一次是需要解码的,后面就都不用解码了,这是Time Profiler的截图:
|
11
lldong 2014-12-08 15:51:59 +08:00
像 Twitter 一样转成视频播放
|
12
Smartype 2014-12-08 20:25:49 +08:00 via iPhone
@jox 所以现在问题很明了了。是因为uiImageview的动画是用cftimer驱动的,而这个timer所在的runloop在滚动的时候被被挂起了,解决的方法要么是处理滚动,续上timer,不让出现跳帧。要么就是cadisplaylink,滚还是不滚,我都要播放。但是滚动的时候我是不关心动画的,我的话,会让滚动完了接着放
|
13
jox OP @Smartype 我也打算在滚动结束之后再继续播放动画!非常感谢!
不过只要gif已经显示了,uiimageview在滚动的时候动画会一直播放,并且滚动很流畅,现在卡顿只有在接下来的需要渲染的table row里有很多数据的时候才会发生 |
16
Smartype 2014-12-08 23:51:12 +08:00 via iPhone
用operation queue或者dispatch asyn在绘制在一个image graphics context里,然后好了后直接把这个丢给main thread显示就好,应该可以做到丝般润滑
|
17
jox OP @Smartype 这个我知道的,我以为你的意思是GPU渲染都能异步进行呢。我现在就是这么做的,拿到数据后在后台把文字都画到image context上,画好后把image设为layer的contents作为背景,然后再把图片异步加进去。就是现在图片这块儿还没处理好,如果一个cell里有好几个gif的话会卡顿。
|
18
jox OP 这个帖子是错误的,使用Image I/O创建的UIImage对象copy之后还是会使用解码过的图片数据,很尴尬,这里我搞错了一些东西,假设有这样的两个属性:
@property (retain, nonatomic) UIImage *retainImage; @property (copy, nonatomic) UIImage *copyImage; 使用Image I/O创建了一个开启缓存的图片,并分别赋值给上面两个属性 UIImage *image = ... self.retainImage = image; self.copyImage = image; 到这里一共存在三个类型为UIImage的指针,两个类型为UIImage的对象,一个是使用Image I/O创建的,一个是在赋值给copyImage属性的时候创建的,ARC会分别计算这两个UIImage对象的引用数来决定是否要释放这些对象所占用的内存,但是需要指出的是,这两个UIImage对象里的_imageRef指向的是同一个地址!Image I/O是根据这个地址来决定是否要使用解码过的图片的,那么我的这个帖子根本就是错误的,如果有人被我误导了,在这里我向你道歉。 也许苹果开发swift的原因之一就是因为有些开发者会像我一样对跟指针相关的东西产生困惑吧,虽然苹果在让使用obj c的开发者尽量远离手动管理内存方面做了很多努力,但是只要使用指针就难免要和程序背后冰冷的机器打交道,哈,不过也不知道v2ex上有多少人能看出来我的这个帖子是错误的呢?如果有人看出来却没有说出来,我只能说兄弟你不厚道啊。 |
19
ichanne 2015-08-06 10:49:55 +08:00
最近在做多个gif动态表情一起发的功能, 卡顿啊
|