Big UIImage scrolling performance - iphone

I have a big UIimage (2000x2000). Image drawed every time on app start, and copied to CALayer.
On Current time i put UIScrollView on main view, and make CALayer with drawn image.
Scrolling on small zoom looks fine. But on min zooming , when whole image visible, image scroll slowed, it becomes not quick responsible on move touch.
So, the question. What can I do, to increase scrolling performance?

The approach I would take is to use a lower resolution version of your image at lower zoom levels (lower = zoomed out).
First, see this post for resizing UIImages.
Respond to the scrollViewDidEndZooming:withView:atScale: method in UIScrollViewDelegate, and switch the images when a certain zoom level is reached. This will take some trial and error to find the correct balance. You may even want to render your image at several different resolutions. Be sure to generate the different sized UIImages in advance so there is no delay while zooming.

Related

Preloading a large image

I have an image with the dimensions of 5534 × 3803, and size of 2.4mb. The UIView references notes that:
"In iOS 3.0 and later, views are no longer restricted to this maximum
size but are still limited by the amount of memory they consume."
When the image loads, it lags for half a second, then slides in. The image sits in the UIImageView at 1024x704, but can be scaled up to 4x that size for the purpose of my app.
Are you able to preload the image in the AppDelegate? Or is there another way of working around having such a large image?
Thanks
EDIT: The scaling is done via UIPinchGestureRecognizer, and scales up and done (scale x4 - x1) based on the image's center point. There is no panning of the image when zoomed in.
Personally, I would try to write a tile-based system (think Google Maps) that slices your big image into a grid of small images to avoid loading in that gigantic image all at once into RAM. I don't really know what your user interactions are for this image, or whether the images are changing or baked into your project, but I'd assume you can let users scroll around since that image is bigger than any iOS screen. With a tile-based system, you only load the images that are on-screen. CATiledLayer is an Apple class for doing just such a thing. That's probably what you want to look into.
See this StackOverflow question for some different approaches. The accepted answer uses code from Apple's sample PhotoScroller project, which may work for your needs and uses CATiledLayer.
This ScrollViewSuite Apple code might also get on your way (check out the Tiling code).

Zoom out on large UIImageView within an UIScrollView

Case: I have a simple piece of code for displaying/zooming/scrolling a large image in an UIImageView->UIScrollView. In this UIScrollView content I want to place buttons to create clickable areas.
Issue: When I zoom in the quality remains proper but, when I zoom out to the highest posible level than the image is getting dotted and some lines aren't visible anymore.
Tried: I tried to regenerate the UIImage with Interpolation Quality on kCGInterpolationHigh and tried to change the size of the image after every zoom change. As you might aspect, no results jet.
I suggest you use a CATiledLayer as the backing layer, as demonstrated by Apple's PhotoScroller sample app. This allows you to prebuild the scaled versions, meaning you can precisely control the interpolation quality with Photoshop/ImageMagick/GIMP etc, rather than relying on UIScrollView's built-in scaling.

How many UIViews can be displayed simultaneously on iOS before running into performance problems?

I'm making an iPhone game and using UIView objects to draw sprites. Most of the time, I have no performance problems. However, once I have around 15 to 20 objects on the screen (and maybe 5 of them moving around), the game becomes considerably slower, especially on the iPhone 3G. The frame rate can drop to as low as a single frame per second.
Is this simply a limitation of using UIView objects, or should iOS be able to handle this many UIView objects on screen at the same time?
In order to isolate the problem, I've made drawing my views very simple — drawing a red rectangle. drawRect is only getting called once per view. The view hierarchy is very simple and shallow. I'm using CADisplayLink to update the UIView locations every frame.
There's very little else going on, so I'd like to hear if anyone else has had success using this number of UIView objects.
The key to my problems ended up being that I had labels on top of my game content. The labels are not opaque, which likely was a large part of the problem, as phix23 suggested.
The first thing that made a big difference was removing a frames per second label that was on top of the content. Having a label that changed content on every frame caused a lot of slowdown.
I also had a large label that displayed on top of much of the game and changed shape when you level up. It turned out that drawing this label on top of everything caused a lot of slowdown as well.
In answer to my original question, I've found that on an iPhone 3G I can support about 30-40 opaque UIViews onscreen at the same time, with 2 or 3 non-opaque views as well. Non-opaque UIViews that change size, shape, or location are by far the worst, and even one of these that covers a significant amount of the screen can quickly cause problems.
If you're setting the opaque property of each view to NO, keep in mind that this seriously affects the speed of drawing the views. If your views aren't transparent, you should leave this set to YES, which is default.
for such type of application you should use CoreGraphics / Quartz / OpenGL but anyway I don't think there is a limitation on such low count. For example if I have a table view with 9 rows and each row has 5 subviews its still displayed acceptable fast. Have you tried using UIView animation to change the position in view?
good luck in learning OpenGL ;)

How to animate 120 images efficiently?

There are 120 images which are 360-degree round shootings of a product showcase, each is 3 degree apart, size 320 x 320 pixels. Displaying the images continuously will give the effect of rotating the product in front of the user.
So far, the performance is far from satisfactory, there is delay in loading and when the user touch to slide to a particular image.
If OpenGL is not an option, what is the recommended way to handle this kind of animation efficiently? Thanks!
I don't really understand your UI but here is my guess:
Your UI is a circle contains a lots of images and all are in the same screen. I think you can show the thumbnail images (50x50-80x80) in the circle and you can store all of thumbnails in memory without big issue. With that size, each of them is just around 8kb. 120 x 9 ~ 1 MB of memory
When you animate to an image, you can load the thumbnail first and then loading the big image in the background. It will create some effects that user see some images not clear and then see it clear. This will also help when users touch some to slide to a particular image. At least, you have something to show.
You can save some memory and loading issue by resizing the big image to be 75-80% of the size 320x320. This one will save you a little bit of time for loading the images and doesn't impact the image's quality a lot. It all depends on your app as well.
You can try to use eager loading. You can load images ahead before you actually animate them. You can have an array to store 3 - 5 images (320 x 320 is not a big size, so 5 of them will just around 500-1000 KB). When you show the first image, you start loading the 4 th image before hand.
If you want to really compress this and have smooth playback on mobile, you should store it as a movie and then use AVFoundation's AVPlayer to have custom playback. You can set it to roughly any frame or change the speed of playback forward or backward and loop to make it seamless. You could, for example, set it up to change the location or play velocity in the movie based on a swipe. It is more work to set up than MPMoviePlayer but is quite customizable.
How about a UIWebView + HTML5?
Look at the apple showcase: http://www.apple.com/html5/showcase/threesixty/
I would make lowres copies of all 120 images, maybe 80x80 in size. All 120 should fit in the GPU's texture cache. Load all 120 images into 120 offscreen image views, zoomed up to 320x320. Animate using those 120 image views, showing one image at a time. Whenever the animation stops, quickly replace the last image with one more view that has the corresponding full resolution 320x320 copy. Whenever the user starts to start to animation, switch back to the lowres set of images.
This works because the eye can't see changing objects (illusion of motion) with the same resolution as they can a static image, depending on the rate of animation of course.

UIImageView and UIImage of equal size

I came across a weird scenario in my code the other day:
I have a UIImageView that loads an image with setImage:. The UIImageView is prior initialized with a frame having the exact size of the image (41*41 px). I also set the content mode to UIViewContentModeCenter, which should ensure my image is never scaled.
Now when I look at my image view I see that the image is a bit cropped horizontally and it appears a little blurred (this is a telltale sign that some rescaling is happening in the background). If instead I initialize my image view with 1 extra pixel in width, all works perfectly (however my image view is now one pixel wider than my image).
Also if I initialize my UIImageView with initWithImage: that seems to work fine too. I checked this view's frame after initialization and I found it to be of the same size: 41*41.
So bottom line is I have a few workarounds for this issue, but I'm trying to understand what's happening here. The only explanations I can think of are:
There is a bug in the framework
The rendering of images doesn't work well for images of a particular size. I know that for examples textures are always powers of 2, though I doubt this has much significance for UIImageView.
For the record I'm compiling for OS 3.0 and the issue happens on both simulator and device.
Is the UIImageView contained inside any other views? One thing I've had before is blurred controls caused by fractional pixel offsets. i.e. if you calculate a frame using division and end up with a non-integer float value then UIKit can add some strange blurring at certain offsets and sizes.
So the image view may have an integer size, but it's absolute frame when taking the parent(s) into consideration may not be.