What is the best way to play an animation frame by frame? - iphone

I draw some GIS data dynamically, based on user's control, into CGImageRef.
But how to play these frame like an animation efficiently in an UIImageView?
After searching and surveying, the way to play an animation in UIImageView is preloading all images you need,and invoking the startanimating method,like this:
myImageView.animationimages=[NSArray arrayWithObjects:1uiimage,2uiimage,....,nil];
[myImageView startAnimating];
But the waiting time is too long if i preload all UIImages, because i have more than 400 frames each time.
I want to play the animation like a stream,real time stream, how to do that?
Deeply appreciating if you could give me any idea or an example. :)

Use CADisplayLink to get notified on each screen refresh. Change myImageView.image in the callback.
(You might have to do something more clever if you want to limit the framerate.)

Related

NSTimer freezes when calling with UIViewAnimation

In my project I am calling NSTimer 1000 times in a second. and with it I am allocating 5 UIImage objects per tap in some image view at same time with UIViewanimation. when I am doing that work the NSTimer freezes for some seconds or delaying. I know why it is happing because I am making more then 100-120 UIImageView objects in a seconds.The timer is dong fine when I am not calling UIAnimation. i Used [performSelectorInBackground:withObject:] to perform UIViewAnimation in the background.but in it the UIAnimation is not working .
Both NSTimer and UIViewAnimation is working on UI.so they are working on main thread. I can not make a different thread for them . what can I do to stop freezing of the NSTimer and calling UIViewAnimation in same time.These is because of the heavy computing. and I can not make sepererate thread for that what can I Do to workthat.
Thanks
That can be happening because of PNG images you are using for animation inside UIImageView.
Why not try using JPEG representation
UIImage *newImage=[UIImage imageWithData:UIImageJPEGRepresentation(myImage, 0.5)];
then use newImage as it will have less size than png one.

Capture specific CALayer (and subviews) to a video file (or data) in Real Time

I have a UIView (with its CALayer) which has a UIImageView as a sub-view.
The UIImageView is animated (imageView.animationImages).
I would like to capture the currently played animation to a video file, or video data (later to be converted to a video file), but not capture all the elements on the screen, like buttons and other UI, but just a specific UIView (not for a promo vid, but as part of the app's functionality).
I tried implementing ScreenCaptureView , but while it does let me capture a specific UIView into a video file in realtime, it won't capture the Animated UIImageView , it shows just the first frame...
I thought about using the CALayer's renderInContext: and then somehow appending the CGImage (current frame) to a video data and then making a video file from the data (or maybe appending directly to a video file).
I'm kinda stuck on the appending part... I don't really know what to do with the render data of the current frame.
Does anyone have any hints or suggestions?
Any help will be much appreciated :)
I made the a change to ScreenCaptureView.m and now it captures the UIImageView animation:
[self.layer renderInContext:context];
changed to:
[self.layer.presentationLayer renderInContext:context];
Although the performance is actually pretty bad on a device (iPhone 4)...

GLKViewController: incorrect fps

Hope there are some GLKViewController experts out there because I have some problems :)
Just a quick description of my app. I have a UINavigationController in which I push different screens.
At some point, I get to my game screen which is a subclass of UINavigationController. In this screen, in viewDidLoad I manually create a EAGLContext, GLKView and instantiate a new GLKViewController (to handle my update&draw calls).
I am setting a preferred fps of 30.
The problem is that the first 3-4 update calls come with the correct DT, but then I have 2-3 frames with 1 second between them. I measure the DT using controller.timeSinceLastUpdate.
So I get like:
dt=0.33
dt=0.33
dt=0.33
dt=1.07
dt=1.05
dt=0.33
dt=0.33
After this, I get valid only DT times. I have no idea why those frames have that kind of delay. I measured the time it takes me in the update & draw method, and it's nowhere near 1 second.
Also, I'm not loading any textures/creating any geometry. Everything is done at loading since it is a rather small game.
Also, if I pop the game screen controller and then push back another instance of the game screen, this new GLKViewController will only call my update method aproximately every 1 second.
Did anybody have a problem with the framerate when using GLKViewController?
Thanks,
The problem is that you don't know what else the device is doing between your refreshes :)
You might only spent 0.1s working on the next frame but if there is a memory warning then other bits of your app will also take time to process. I guess that the gl controller will do it's best to keep to the preferred frame rate but if lots is going on in the background then there's not much it can do about it.
As long as you make sure that your code is rendering as fast as possible and isn't spiking in the same way as the framerate then it's not your render path. From your question it sounds like you've already tested that.
The other thing you might want to do is to watch out for other notifications that might be passed into your app (i.e. memory warnings).
Finally, is there a pattern to the slow frames - do they coincide with a new image being loaded or a file access? Have you done as much as possible beforehand? EDIT - rereading your question makes me think that you've already done this, sorry!
Sorry I can't be any more use :(
Ok, so I finally figured it out. It turns out that it's not even related to the GLKViewController (surprise surprise!).
It had something to do with the way I'm displaying the game screen view controller, like this:
GameAreaViewController* gameController = [[GameAreaViewController alloc] init];
[UIView beginAnimations:#"animation" context:nil];
[self.navigationController pushViewController: gameController animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView setAnimationDuration:0.7f];
[UIView commitAnimations];
SAFE_DEL(gameController);
If I use an animation duration of 0.3f, then I don't get any lag. At 0.5f sometimes I get it and at 0.7 I was always getting it.

UIImageView causes lag first time they are displayed

I have a couple of UIViews with UIImageViews on them. When I display a view the first time, there is a noticeable lag (0.5 second or so) before it is shown. When shown again everything works.
I have managed to work around this by adding all views and then removing them. Like this:
[self performSelectorOnMainThread:#selector(addAndRemoveAllViews)
withObject:nil
waitUntilDone:NO];
The function loops over all views and [addSubview:view] followed by [view removeFromSuperview]. This seems to trigger the images to load while not being shown.
Questions:
This all feels like a workaround to me. Is there a better approach to handle these types of things?
Is it possible to get a callback or something when it's completed? I want to run an animation when done.
Update:
Images are created from NSData like this:
[[UIImageView alloc] initWithImage:[UIImage imageWithData:rawData]];
It seems very likely the image is larger than the image view. If possible shrink it down to the size the image view needs.
The initial delay is loading the image from storage, after that you are using a cached version which is why it is faster.

Cocoa-Touch How to: MPMoviePlayerController loop?

I have an app with a splash screen. For the splashscreen I've decided to add a m4v movie. I'm using the MPMoviePlayerController to show the movie. Everything is working as expected except for one thing:
I'm trying to make the MPMoviePlayerController loop by subscribing to it's MPMoviePlayerPlaybackDidFinishNotification notification and issuing a [notification.object play] if the data didn't finish loading.
This works partially, it restarts the movie, but there's the fadeout and re-fadein that make it look bad.
Is there any other way to loop the movie?
Or any way to remove the fades?
Try this single line of code:
myPlayer.repeatMode = MPMovieRepeatModeOne;
:)
By complete coincidence I have just written a blog post on this subject - we ran into this problem while we were writing our latest app :)
Assuming that you don't want to follow my shameless plug, here's how we fixed it :
Make sure that the movie starts
and ends on the same frame.
Make the starting frame the Default.png of the app
On startup add Default.png to the window as a UIImageView
Make the movie have a clear background
Play and loop the movie
When the movie ends, it will fade out before it loops round. As Default.png is exactly the same as the start and end frames, the user will never notice :)
When you want to end the movie just remove the Default.png UIImageView and stop the movie - as the background is clear it will just fade out to whatever ui you have in your window.
Sam
I don't think there is any public option to do this. You could try and inspect Erica Sadun's Class Dumps for a method you can override that would handle the fading. Maybe a videoDidFinish method or something.
Have you tried messing around with the backgroundColor property? Apple's MPMoviePlayerController docs say
"The receiver fades to and from the
background color when transitioning to
and from playback...The default color
for this property is black. You can
change this to other colors (including
clear) to provide a more appropriate
transition from your application’s
content to the movie content."
So, you can probably try setting it to [UIColor clearColor] and seeing if that helps.