4

Currently I have a PNG animation on a timer that is firing every .01 seconds. However, performance isn't optimal and the animation is visibly slow. I have over 2000 images. Is there a better way to accomplish this? I've posted something similar to my approach below.

timer_ = [NSTimer scheduledTimerWithTimeInterval:.01 target:self
selector:@selector(switchImage) userInfo:nil repeats:YES];


-(void)switchImage 
{
   p = [p stringByAppendingFormat:@"/Movie Clipping 1 000%i.png",i];
   imageView_.image = [UIImage imageWithContentsOfFile:p];
   i = i++;
}
Brandon Schlenker
  • 5,078
  • 1
  • 36
  • 58
  • Why did you originally choose to use .png frames instead of a single .mp4 video? The iPhone handles H.264 very well. – Spencer Hakim Nov 08 '10 at 20:58
  • I need the flexibility of pausing ands scrubbing the animation as well as the ability to swap out frames. – Brandon Schlenker Nov 08 '10 at 21:00
  • 1
    Ah, ok. You'll need to use OpenGL to render the frames, UIImage is (as you've learned) too slow for this. I'm not familiar enough with OpenGL to tell you exactly how to do it, but hopefully someone will see this and contribute. – Spencer Hakim Nov 08 '10 at 21:03
  • Yeah, I was thinking that may be an option. Surely there's some sample code somewhere on how to do it. – Brandon Schlenker Nov 08 '10 at 21:04

3 Answers3

7

exactly what size (I mean KB and also the exact pixel size) are your PNGs?

We have done a lot of work on this and have no trouble playing animations, on the pad, of about say 500x500. So I'm just wondering, thanks.

One immediate problem is that you are trying to run at 100hz, 100 times per second??!

That is absolutely impossible. Nothing runs at 100 fps. 20fps is "extremely smooth", 30fps is "staggeringly smooth", 40fps is "mindboggling human-vision-research-level smooth if it could be achieved" and 100 fps cannot be achieved.

This has absolutely utterly nothing whatsoever to do with OpenGLES.

The ordinary environment will load frames very quickly for you.

So first go back to 30 fps (at most!) and throw away every 2nd and 3rd image so the animation looks the same. ie, "i=i++" becomes "i+=3" in your line of code.

it is likely that this is the overwhelming problem that is ruining your efforts!

Next problem! If you do load up each image like that as you go, you will almost certainly need to release them all on the fly as you go with a pair of lines something like...

[happy.image release];
happy.image = [[UIImage alloc] initWithContentsOfFile:
    [[NSBundle mainBundle] pathForResource:@"blah" ofType:@"png"]];

If you don't do that it just won't work.

Next problem! The idea of using video is no good, but could you just use an everyday animated image? Thus...

#define BI(X) [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@X ofType:@"tif"]]

    happyDays  = [[NSArray alloc] initWithObjects:
            BI("hh00"), BI("hh01"), BI("hh02"), BI("hh03"), BI("hh04"), BI("hh05"), BI("hh06"), BI("hh07"), BI("hh08"), BI("hh09"), 
            BI("hh10"), BI("hh11"), BI("hh12"), BI("hh13"), BI("hh14"), BI("hh15"), BI("hh16"), BI("hh17"), BI("hh18"), BI("hh19"), etc etc etc
            nil];

    animArea.animationImages = happyDays;
    animArea.animationDuration = 2.88;
    // that is overall seconds. hence: frames divided by about 30 or 20.
    [animArea startAnimating];

No good for your situation?

Anyway, in one word your problem is 100 fps. Change to 20 fps and you will have no trouble. And let us know the precise image size (kb / x.y).

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • I actually found a solution that allows me to use MPMoviePlayerController, however this is great knowledge to have and I'll definitely use it in the future. Thanks so much. – Brandon Schlenker Nov 09 '10 at 18:18
  • 1
    Developers should be aware that use of UIImageView.animationImages is a very bad idea, it will crash your app on the device when memory runs low. My blog on this topic covers the issue: http://iosgraphicsanimation.wordpress.com/2013/06/11/video-and-memory-usage-on-ios-devices/ – MoDJ Jun 20 '13 at 22:14
1

How about CADisplayLink for managing fps?

OpenGLES needs to spend time to convert an image to texture, and texture needs careful memory management. When memory is not enough, it will generate a whole white texture.

AechoLiu
  • 17,522
  • 9
  • 100
  • 118
  • You are right. :) I had made a OpenGLES component, and it still needs CADisplayLink or NSTimer to manage fps. The time for generating a texture is bigger than loading an image directly. – AechoLiu Nov 10 '10 at 08:32
-1

Encode your animation as a video and play the video instead.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • No, it definitely needs to be an animation because I need the flexibility of modifying frames. I've had this problem before though with image sequences that are much shorter. Is there a more efficient way to do this? – Brandon Schlenker Nov 08 '10 at 20:58
  • You can always just go back, edit the animation, and then re-encode it. – Spencer Hakim Nov 08 '10 at 21:00