天天看点

iOS中播放gif动态图的方式探讨

    在ios开发中,uiimageview类专门来负责图片数据的渲染,并且uiimageview也有帧动画的方法来播放一组图片,但是对于gif类型的数据,uiimageview中并没有现成的接口提供给开发者使用,在ios中一般可以通过两种方式来播放gif动态图,一种方式是通过imageio框架中的方法将gif文件中的数据进行解析,再使用coreanimation核心动画来播放gif动画,另一种方式计较简单,可以直接通过webview来渲染gif图。

     gif动态图文件中包含了一组图片及其信息,信息主要记录着每一帧图片播放的时间,我们如果获取到了gif文件中所有的图片同时又获取到每一帧图片播放的时间,就可以为uiimageview添加核心动画的方法来让其播放gif的内容了。

    首先解析gif文件中的数据,代码如下:

<a href="http://my.oschina.net/u/2340880/blog/608560#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

<code>//要引入imageio库</code>

<code>#import &lt;imageio/imageio.h&gt;</code>

<code>//解析gif文件数据的方法 block中会将解析的数据传递出来</code>

<code>-(</code><code>void</code><code>)getgifimagewithurk:(nsurl *)url</code>

<code>               </code><code>returndata:(</code><code>void</code><code>(^)(nsarray&lt;uiimage *&gt; * imagearray,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;*timearray,</code>

<code>                                </code><code>cgfloat totaltime,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;* widths,</code>

<code>                                </code><code>nsarray&lt;nsnumber *&gt;* heights))datablock{</code>

<code>    </code><code>//通过文件的url来将gif文件读取为图片数据引用</code>

<code>    </code><code>cgimagesourceref source = cgimagesourcecreatewithurl((cfurlref)url, null);</code>

<code>    </code><code>//获取gif文件中图片的个数</code>

<code>    </code><code>size_t</code> <code>count = cgimagesourcegetcount(source);</code>

<code>    </code><code>//定义一个变量记录gif播放一轮的时间</code>

<code>    </code><code>float</code> <code>alltime=0;</code>

<code>    </code><code>//存放所有图片</code>

<code>    </code><code>nsmutablearray * imagearray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每一帧播放的时间</code>

<code>    </code><code>nsmutablearray * timearray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每张图片的宽度 (一般在一个gif文件中,所有图片尺寸都会一样)</code>

<code>    </code><code>nsmutablearray * widtharray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//存放每张图片的高度</code>

<code>    </code><code>nsmutablearray * heightarray = [[nsmutablearray alloc]init];</code>

<code>    </code><code>//遍历</code>

<code>    </code><code>for</code> <code>(</code><code>size_t</code> <code>i=0; i&lt;count; i++) {</code>

<code>        </code><code>cgimageref image = cgimagesourcecreateimageatindex(source, i, null);</code>

<code>        </code><code>[imagearray addobject:(__bridge uiimage *)(image)];</code>

<code>        </code><code>cgimagerelease(image);</code>

<code>        </code><code>//获取图片信息</code>

<code>        </code><code>nsdictionary * info = (__bridge nsdictionary*)cgimagesourcecopypropertiesatindex(source, i, null);</code>

<code>        </code><code>cgfloat width = [[info objectforkey:(__bridge nsstring *)kcgimagepropertypixelwidth] floatvalue];</code>

<code>        </code><code>cgfloat height = [[info objectforkey:(__bridge nsstring *)kcgimagepropertypixelheight] floatvalue];</code>

<code>        </code><code>[widtharray addobject:[nsnumber numberwithfloat:width]];</code>

<code>        </code><code>[heightarray addobject:[nsnumber numberwithfloat:height]];</code>

<code>        </code><code>nsdictionary * timedic = [info objectforkey:(__bridge nsstring *)kcgimagepropertygifdictionary];</code>

<code>        </code><code>cgfloat </code><code>time</code> <code>= [[timedic objectforkey:(__bridge nsstring *)kcgimagepropertygifdelaytime]floatvalue];</code>

<code>        </code><code>alltime+=</code><code>time</code><code>;</code>

<code>        </code><code>[timearray addobject:[nsnumber numberwithfloat:</code><code>time</code><code>]];</code>

<code>    </code><code>}</code>

<code>    </code><code>datablock(imagearray,timearray,alltime,widtharray,heightarray);</code>

<code>}</code>

为uiimageview添加一个设置gif图内容的方法:

<code>-(</code><code>void</code><code>)yh_setimage:(nsurl *)imageurl{</code>

<code>        </code><code>__weak id __self = self;</code>

<code>        </code><code>[self getgifimagewithurk:imageurl returndata:^(nsarray&lt;uiimage *&gt; *imagearray, nsarray&lt;nsnumber *&gt; *timearray, cgfloat totaltime, nsarray&lt;nsnumber *&gt; *widths, nsarray&lt;nsnumber *&gt; *heights) {</code>

<code>            </code><code>//添加帧动画</code>

<code>            </code><code>cakeyframeanimation *animation = [cakeyframeanimation animationwithkeypath:@</code><code>"contents"</code><code>];</code>

<code>            </code><code>nsmutablearray * times = [[nsmutablearray alloc]init];</code>

<code>            </code><code>float</code> <code>currenttime = 0;</code>

<code>            </code><code>//设置每一帧的时间占比</code>

<code>            </code><code>for</code> <code>(</code><code>int</code> <code>i=0; i&lt;imagearray.count; i++) {</code>

<code>                </code><code>[times addobject:[nsnumber numberwithfloat:currenttime/totaltime]];</code>

<code>                </code><code>currenttime+=[timearray[i] floatvalue];</code>

<code>            </code><code>}</code>

<code>            </code><code>[animation setkeytimes:times];</code>

<code>            </code><code>[animation setvalues:imagearray];</code>

<code>            </code><code>[animation settimingfunction:[camediatimingfunction functionwithname:kcamediatimingfunctionlinear]];</code>

<code>            </code><code>//设置循环</code>

<code>            </code><code>animation.repeatcount= maxfloat;</code>

<code>            </code><code>//设置播放总时长</code>

<code>            </code><code>animation.duration = totaltime;</code>

<code>            </code><code>//layer层添加</code>

<code>            </code><code>[[(uiimageview *)__self layer]addanimation:animation forkey:@</code><code>"gifanimation"</code><code>];</code>

<code>        </code><code>}];</code>

使用代码示例如下:

<code>    </code><code>uiimageview * imageview = [[uiimageview alloc]initwithframe:cgrectmake(0,0 , 320, 200)];</code>

<code>    </code><code>nsurl * url = [[nsurl alloc]initfileurlwithpath:[[nsbundle mainbundle] pathforresource:imagename oftype:nil]];</code>

<code>    </code><code>[imageview yh_setimage:url];</code>

<code>    </code><code>[self.view addsubview:imageview];</code>

iOS中播放gif动态图的方式探讨

    ios中的uiwebview功能十分强大,可以通过uiwebview为载体,来展示gif图。并且这种方法也十分简单,代码如下:

<code>         </code><code>//读取gif数据</code>

<code>         </code><code>nsdata *gifdata = [nsdata datawithcontentsofurl:imageurl];</code>

<code>        </code><code>uiwebview *webview = [[uiwebview alloc] initwithframe:cgrectmake(0, 0, self.frame.size.width, self.frame.size.height)];</code>

<code>        </code><code>//取消回弹效果</code>

<code>        </code><code>webview.scrollview.bounces=no;</code>

<code>        </code><code>webview.backgroundcolor = [uicolor clearcolor];</code>

<code>        </code><code>//设置缩放模式</code>

<code>        </code><code>webview.scalespagetofit = yes;</code>

<code>        </code><code>//用webview加载数据</code>

<code>        </code><code>[webview loaddata:gifdata mimetype:@</code><code>"image/gif"</code> <code>textencodingname:nil baseurl:nil];</code>

    经过测试,从加载速度上来说,通过uiimageview类别加载的方式更加快速,uiwebview的方式加载时间会稍长,但是从性能上来比较,webview的方式性能更优,播放的gif动态图更加流畅。在开发中,可以根据需求,适当选择,例如虽然webview加载的方式性能更好,但是在许多情况下,原生的uiimageview能够更加自由的让开发者进行扩展。

继续阅读