- Update 2010-01-22: Major rework of the module, making stuff even easier, and having better memory management..
I recently started developing for iPhone, and I was looking to include some simple animations into my applications, like a typical AJAX loading GIF when I’m waiting for my stream of data to come in.
It surprised me that nothing was available! After a lot of searching I found a block of code by Martin van Spanje from P-Edge. It was based on some PHP code, splitting an animated GIF in subframes.
The code worked, Martin stated it needed to be checked and optimized. So I went to work. I upped the code to the GIF 89a standards, I created a class out of it. Best of all, I got animation working WITH transparency! I believe in Apple’s idea of simplicity, so I made a set of interfaces that -anyone- should be able to use. Here’s what you need to open up a GIF, and set it up to animate in your project:
// First example, a local file NSURL* firstUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"apple_logo_animated" ofType:@"gif"]]; UIImageView * firstAnimation = [AnimatedGif getAnimationForGifAtUrl: firstUrl]; // Second example, through HTTP NSURL * secondUrl = [NSURL URLWithString:@"http://www.gifs.net/Animation11/Food_and_Drinks/Fruits/Apple_jumps.gif"]; UIImageView * secondAnimation = [AnimatedGif getAnimationForGifAtUrl: secondUrl]; // Add them to the view. [theFirstAnimatedGif addSubview:firstAnimation]; [theSecondAnimatedGif addSubview:secondAnimation];
Best of all, I’m releasing this FREE for commercial use as well, as long as you keep the permission notice in the source files!
The download consists of the AnimatedGif class (.h and .m files), and the code should be self-explanatory. Should you require any help: leave a comment, or mail me! (email in example project result, or in my Curriculum Vitea)
Download just the class:
AnimatedGif Class (1390)
Download an example XCode 3.1.3 project
AnimatedGif Example Project (1538)
// Changelog: // // 2010-03-16: Added queing mechanism for static class use // 2010-01-24: Rework of the entire module, adding static methods, better memory management and URL asynchronous loading // 2009-10-08: Added dealloc method, and removed leaks, by Pedro Silva // 2009-08-10: Fixed double release for array, by Christian Garbers // 2009-06-05: Initial Version
28 Comments »
animated gifs only show first frame? - iPhone Dev SDK Forum @ Sunday, July 5th, 2009
[...] Originally Posted by Wizfinger Animated GIF's only display the first frame in a UIImage. To get all of the frames, the GIF image needs to be decoded first. Crude example code can be found here: iPhone developer: decoding an animated GIF image in Obj-C – Pliep.nl I fixed all this, and put it in a simple class. My class also support transparency . It's free to use commercially, as long as you leave an attribution in the code to me. Take a look here [...]
Pliep @ Sunday, July 5th, 2009
Nice one!
Does it also support LZH compressed images and animation frames?
By the way, in iPhone OS 3.0 animated GIFs are supported (including animation) by UIWebView. UIImageView still does not support animated GIF images.
Stijn Spijker @ Sunday, July 5th, 2009
If the Cocoa iPhone framework does, this probably does as well, as your original code (and the part I added) leave the actual headers alone. I don’t know how to make an LZH compressed GIF though, so if you can give me one I can try
Expect bugs, haha!
I hadn’t heard about the UIWebView supporting animated GIF, but will the UIWebView object you use to load the GIF support the transparency?
I’m just getting into Cocoa, this is my first real piece of code for the iPhone so
Pliep @ Tuesday, July 7th, 2009
Hi Stijn,
I tried your class and it is nicely done. I found that compressed GIF frames do not work
because any compressed frame needs to be combined with the previous frame to het a full image.
Unfortunately I’ve not been able to figure out how to implement it.
Example image:
http://www.p-edge.nl/downloads/gen4.gif
Some frames of the image are fully stored (such as the first frame), but other frames are compressed and only contain changes that have to be applied to the frame before it.
For example, the second frame is compressed and needs to be masked upon the first frame to create a complete second frame image.
This can be done by using CGImageCreateWithMaskingColors. Code here:
http://www.p-edge.nl/downloads/maskimageframe.m
The first frame can be saved immediately, and consecutive frames can be applied by using – maskFrame: withFrame:
However…. animated GIF images may also contain several frames that are “stand-alone”, and those do NOT have to be masked upon their predecessor.
I’ve not been able to find out how in de GIF specifications how to detect if a frame can be displayed “as is” or of it needs to be applied to the previous frame.
If you can be of any assistance, please build it into your class
thanks,
Pliep
Stijn Spijker @ Tuesday, July 7th, 2009
Thanks for the info Pliep,
I’ll certainly take a try at implementaing LZH compressed frames, I’ve already tried some stuff with the masked colors.
I’m pretty busy at the moment, but I’ll let you know when I implemented it.
Doug @ Tuesday, July 14th, 2009
Hey Stijn, thanks for making this code available, it saved me a lot of time. Just wanted to point out to anyone else who may be dealing with compressed frames that you can get rid of this optimization using a tool like gifsicle:
http://www.lcdf.org/gifsicle/
For my gif, all I had to do was:
gifsicle -U compressed.gif > uncompressed.gif
The resulting uncompressed.gif looked great using your AnimatedGif class.
Antti Kupila @ Sunday, August 23rd, 2009
Being able to encode gifs too would be awesome. Do you have any plans on continuing to work on this?
Steve-O @ Friday, August 28th, 2009
Thanks for the example project – it helps a TON.
One thing that I could not do was to slow down the animation more than one step.
My Gif reacts like it had too much coffee…. My slow down teak looks like….
// Count up the total delay, since Cocoa doesn’t do per frame delays.
// TIME DELAY BETWEEN FRAMES (adjust int i = 0 to i = 1 )
NSTimeInterval total = 0;
for (int i = 1; i < [GIF_delays count]; i++)
{
total += [[GIF_delays objectAtIndex:i] doubleValue];
}
any tips to slow down even more?
Steve-O @ Friday, August 28th, 2009
Oh, I also tried changing
NSTimeInterval total = 0;
to NSTimeInterval total = 1;
and even tried messing with
// GIFs store the delays as 1/100th of a second.
[uiv setAnimationDuration:total/100];
StijnSpijker @ Wednesday, September 2nd, 2009
The last one should do the trick, the AnimationDuration contains the time for the -total- animation to complete.
So say that you want your animation to animate over a period of 4 seconds, you do:
[uiv setAnimationDuration: 4];
drahn @ Friday, October 30th, 2009
I am running into a problem when implementing this where my images seem to be missing large amounts of the image. It looks like only the differences are being displayed or theirs some issue with the transparency. I display the animated gif images fine in safari on mac and pc and in safari on the iphone.
I am using CS3 to generate the images and have tried several different methods thinking it is something in my saving process. Any suggestions?
Stijn Spijker @ Sunday, November 8th, 2009
You are probably saving an LZH compressed gif, try unchecking. Any optimize flags or compress checkmarks..
Dredlockz @ Tuesday, January 26th, 2010
I’m also quite amazed by the fact that there’s no way to get a custom loading GIF when waiting for data to come in.
I’ve seen the classic clockwise animation all the time tho, I’m guessing that’s a build-in animation of some sort?
Anyway, thanks for the class, it couldn’t get any easier!
Stijn Spijker @ Tuesday, January 26th, 2010
@Dredlockz
Yes, thats the UIActivityIndicator you’re talking about, it’s default in the UIKit
For all of you who haven’t noticed, this modules has under gone some major rework last weekend, as detailed in this post. As far as I tested it should be backward compatible with old code, but you should use the new code as it uses a shared object to create gifs, which saves memory!
Programming Iphone API and Tips » Blog Archive » Animate a gif in native applications @ Monday, February 1st, 2010
[...] More info here http://blog.stijnspijker.nl/2009/07/animated-and-transparent-gifs-for-iphone-made-easy [...]
burc @ Monday, February 1st, 2010
i think there is a problem if you call the “getAnimationFor GifAtUrl” more than once in an interval shorter than for the “asynchronouslyLoading” to start.
suppose you have a view and you want to add 2 different subviews with 2 separate gifs.
when you call [AnimatedGif getAnimationForGifAtUrl: ] twice in a row, the imageView members gets overwritten by the second call.
You can duplicate the problem in your sample code by adding
[theAnimatedGif addSubview:[AnimatedGif getAnimationForGifAtUrl: url]] after [theAnimatedGif addSubview:animation]
i think to work properly you should keep a list of (imageview, url) pairs and make sure that the asynchronousLoading function works on the appropriate instance.
Sam @ Thursday, February 4th, 2010
Hi this is very nice of you to make..
Any chance of making the encoder to GIF too?
(Like, taking a string of images and encode it to uncompressed GIF single file would be great)
Toby @ Friday, February 5th, 2010
Wow! This was exactly what I needed. You are a super-super-awesome guy! Thanks a bunch!
Stijn Spijker @ Wednesday, March 17th, 2010
Okay, I fixed the multi-image stuff through a queue as suggested by burc. Also moved to a new server, so the download links were broken for a while, sorry! Pruned some old comments about the memory leaks, those are long solved. Everything should be okay now!
SQuat @ Wednesday, March 17th, 2010
Thanks ;p
Jollon @ Tuesday, May 18th, 2010
Hi Stijn Spijker, and thx for the good job
i have some problem with certain gif
for example
http://www.carloneworld.it/Humor_9_emoticon_3D.htm
the frame are corrupted during the animation
do you know why?
kota @ Wednesday, May 19th, 2010
Hello,
I have the same problem as Jollon’s.
Some of my gif images are not converted properly.
Those images are not broken since when I put them into UIWebView, they animate correctly.
Do you have any idea?
Thanks in advance.
Shinya @ Saturday, May 22nd, 2010
Thank you for your great work.
I’ve modified it so that it works with optimized animated GIFs.
http://github.com/kasatani/AnimatedGifExample
You can find the details about the optimized GIFs here: http://www.webreference.com/dev/gifanim/
I still don’t know why those penguins move too fast if you test it with this class though
Jollon @ Thursday, May 27th, 2010
@Shinya
thx for your mod with optimized gif
i found only a little problem with a kind of gif
like this
http://www.allweb.it/images/4_Humor/emoticon_3d/emoticon_3d_53.gif
http://www.allweb.it/images/4_Humor/emoticon_3d/emoticon_3d_5.gif
TBussinger @ Monday, August 30th, 2010
Could you post an example of how to add the gif to a project programmatically, Without the use of a Xib? Thanks.
TBussinger @ Monday, August 30th, 2010
Got It!
- (void)loadYourImageView {
NSURL *firstUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@”gifTitle” ofType:@”gif”]];
UIImageView *yourImageView = [AnimatedGif getAnimationForGifAtUrl: firstUrl];
[yourImageView setContentMode:UIViewContentModeScaleAspectFit];
[loadingImgView setFrame:CGRectMake(0, -40, 320, 460)];
[self addSubview:YourImageView];
}
TBussinger @ Tuesday, August 31st, 2010
Change that “loadingImgView” to whatever your ImageView is named. My bad
lindama @ Wednesday, September 1st, 2010
I add it to a scroll view.
But I can’t release all memory, I will be crash after less than 10 pics.
How can I release gif memory.
RSS feed for comments on this post. TrackBack URI