Home>

We know that gifs are composed of bursts of pictures,And each frame may be played at different times.Looking at the two examples above,It was found that they did not often deal with the display of each frame in the gif.The result is that each frame in the entire gif is played forward at a fixed speed.Obviously this will not always meet the needs.

I wrote my own tool for parsing gifs.Solve each frame and play according to the display time corresponding to each frame.

The idea of ​​the program is as follows:

1. First use the gif file of cgimagesource in the imageio library.

2, get the total number of frames in the gif file through cgimagesource,And the display time of each frame.

3, through cakeyframeanimation to complete the gif animation playback.

The following is the code of the tool class that I wrote to parse and play gifs:

</p>
<p>
//
//svgifview.h
//svgifsample
//
//created by maple on 3/28/13.
//copyright (c) 2013 smileevday. all rights reserved.
//
</p>
<p>
#import<uikit/uikit.h>
</p>
<p>
@interface svgifview:uiview
</p>
<p>
/*
* @brief desingated initializer
* /
-(id) initwithcenter:(cgpoint) center fileurl:(nsurl *) fileurl;
</p>
<p>
/*
* @brief start gif animation
* /
-(void) startgif;
</p>
<p>
/*
* @brief stop gif animation
* /
-(void) stopgif;
</p>
<p>
/*
* @brief get frames image (cgimageref) in gif
* /
+ (nsarray *) framesingif:(nsurl *) fileurl;
</p>
<p>
@end
</p>
<p>
//
//svgifview.m
//svgifsample
//
//created by maple on 3/28/13.
//copyright (c) 2013 smileevday. all rights reserved.
//
</p>
<p>
#import "svgifview.h"
#import<imageio/imageio.h>
#import<quartzcore/coreanimation.h>
</p>
<p>
/*
* @brief resolving gif information
* /
void getframeinfo (cfurlref url, nsmutablearray * frames, nsmutablearray * delaytimes, cgfloat * totaltime, cgfloat * gifwidth, cgfloat * gifheight)
{
 cgimagesourceref gifsource=cgimagesourcecreatewithurl (url, null);
 //get frame count
 size_t framecount=cgimagesourcegetcount (gifsource);
 for (size_t i=0;i<framecount;++ i) {
 //get each frame
 cgimageref frame=cgimagesourcecreateimageatindex (gifsource, i, null);
 [frames addobject:(id) frame];
 cgimagerelease (frame);
 //get gif info with each frame
 nsdictionary * dict=(nsdictionary *) cgimagesourcecopypropertiesatindex (gifsource, i, null);
 nslog (@ "kcgimagepropertygifdictionary%@", [dict valueforkey:(nsstring *) kcgimagepropertygifdictionary]);
 //get gif size
 if (gifwidth!=null&&gifheight!=null) {
 * gifwidth=[[dict valueforkey:(nsstring *) kcgimagepropertypixelwidth] floatvalue];
 * gifheight=[[dict valueforkey:(nsstring *) kcgimagepropertypixelheight] floatvalue];
 }
 //The values ​​of kcgimagepropertygifdelaytime and kcgimagepropertygifunclampeddelaytime in kcgimagepropertygifdictionary are the same
 nsdictionary * gifdict=[dict valueforkey:(nsstring *) kcgimagepropertygifdictionary];
 [delaytimes addobject:[gifdict valueforkey:(nsstring *) kcgimagepropertygifdelaytime]];
 if (totaltime) {
 * totaltime=* totaltime + [[gifdict valueforkey:(nsstring *) kcgimagepropertygifdelaytime] floatvalue];
 }
 }
}
</p>
<p>
@interface svgifview () {
 nsmutablearray * _frames;
 nsmutablearray * _framedelaytimes;
 cgfloat _totaltime;//seconds
 cgfloat _width;
 cgfloat _height;
}
</p>
<p>
@end
</p>
<p>
@implementation svgifview
</p>
<p>
-(id) initwithcenter:(cgpoint) center fileurl:(nsurl *) fileurl;
{
 self=[super initwithframe:cgrectzero];
 if (self) {
 _frames=[[nsmutablearray alloc] init];
 _framedelaytimes=[[nsmutablearray alloc] init];
 _width=0;
 _height=0;
 if (fileurl) {
 getframeinfo ((cfurlref) fileurl, _frames, _framedelaytimes,&_totaltime,&_width,&_height);
 }
 self.frame=cgrectmake (0, 0, _width, _height);
 self.center=center;
 }
 return self;
}
</p>
<p>
+ (nsarray *) framesingif:(nsurl *) fileurl
{
 nsmutablearray * frames=[nsmutablearray arraywithcapacity:3];
 nsmutablearray * delays=[nsmutablearray arraywithcapacity:3];
 getframeinfo ((cfurlref) fileurl, frames, delays, null, null, null);
 return frames;
}
</p>
<p>
-(void) startgif
{
 cakeyframeanimation * animation=[cakeyframeanimation animationwithkeypath:@"contents"];
 nsmutablearray * times=[nsmutablearray arraywithcapacity:3];
 cgfloat currenttime=0;
 int count=_framedelaytimes.count;
 for (int i=0;i<count;++ i) {
 [times addobject:[nsnumber numberwithfloat:(currenttime/_totaltime)]];
 currenttime +=[[_framedelaytimes objectatindex:i] floatvalue];
 }
 [animation setkeytimes:times];
 nsmutablearray * images=[nsmutablearray arraywithcapacity:3];
 for (int i=0;i<count;++ i) {
 [images addobject:[_ frames objectatindex:i]];
 }
 [animation setvalues:images];
 [animation settimingfunction:[camediatimingfunction functionwithname:kcamediatimingfunctionlinear]];
 animation.duration=_totaltime;
 animation.delegate=self;
 animation.repeatcount=5;
 [self.layer addanimation:animation forkey:@"gifanimation"];
}
</p>
<p>
-(void) stopgif
{
 [self.layer removeallanimations];
}
</p>
<p>
//remove contents when animation end
-(void) animationdidstop:(caanimation *) anim finished:(bool) flag
{
 self.layer.contents=nil;
}
</p>
<p>
//only override drawrect:if you perform custom drawing.
//an empty implementation adversely affects performance during animation.
-(void) drawrect:(cgrect) rect
{
 //drawing code
}
</p>
<p>
@end

The code is short and easier,I won't explain them one by one.The first c function is mainly used to parse the gif. The reason why I use the c function is because I want to return multiple informationObjective-c can only return one parameter,And objective-c and c language can be easily mixed with programming.

In addition, two methods of using uiimageview are introduced:

1. Play with uiwebview

//set position and size
 cgrect frame=cgrectmake (50,50,0,0);
 frame.size=[uiimage imagenamed:@"guzhang.gif"]. size;
 //read gif image data
 nsdata * gif=[nsdata datawithcontentsoffile:[[nsbundle mainbundle] pathforresource:@"guzhang" oftype:@"gif"]];
 //view generation
 uiwebview * webview=[[uiwebview alloc] initwithframe:frame];
 webview.userinteractionenabled=no;//Users cannot interact
 [webview loaddata:gif mimetype:@"image/gif" textencodingname:nil baseurl:nil];
 [self.view addsubview:webview];
 [webview release];

2. Break the gif image into multiple png images and play them using uiimageview.

code show as below:

uiimageview * gifimageview=[[uiimageview alloc] initwithframe:[[uiscreen mainscreen] bounds]];
 nsarray * gifarray=[nsarray arraywithobjects:[uiimage imagenamed:@"1"], [uiimage imagenamed:@"2"], [uiimage imagenamed:@"3"], [uiimage imagenamed:@"4"], [uiimage imagenamed:@"5"], [uiimage imagenamed:@"6"], [uiimage imagenamed:@"7"], [uiimage imagenamed:@"8"], [uiimage imagenamed:@"9"], [uiimage imagenamed:@"10"], [uiimage imagenamed:@"11"], [uiimage imagenamed:@"12"], [uiimage imagenamed:@"13"], [uiimage imagenamed:@"14"], [uiimage imagenamed:@"15"], [uiimage imagenamed:@"16"], [uiimage imagenamed:@"17"], [uiimage imagenamed:@"18"], [uiimage imagenamed:@"19"], [uiimage imagenamed:@"20"], [uiimage imagenamed:@"21"], [uiimage imagenamed:@"22"], nil];
 gifimageview.animationimages=gifarray;//animated image array
 gifimageview.animationduration=5;//Time required to execute a complete animation
 gifimageview.animationrepeatcount=1;//Number of animation repetitions
 [gifimageview startanimating];
 [self.view addsubview:gifimageview];
 [gifimageview release];

Note:This method,If the time interval between gif animations is different,This effect cannot be achieved.

ios
  • Previous What to do if mysql installation fails
  • Next SQL Server 2008 login with 'sa' failed, solution to enable 'sa' login