Large UIImage causing low memory and crashes - iphone

I have a large image that I load into a UIImageView. The image is a PNG and it's #2x file size is: 384K. The image is 5119x2413 pixels. The image can be zoomed by the user by using pinch gestures. The reason the image is so large is so that when the UIImageView is transformed by pinching the quality will stay the same.
The problem I'm having is that on some devices especially the latest iPod Touch it will crash while attempting to display this screen.
I've ran the app via Instruments and profiled it using the Leak/Allocations profiles. The app's live bytes generally hovers around 4MB when using the app, but as soon as you view the screen containing the UIImageView this shoots up to 40MB! Onces the image is on the screen the memory returns to around 4MB.
The problem I'm having is that more times than not on older devices and ones limited by memory like the iPod Touch my app is being terminated by the system, along with some system services like SpringBoard.
I've tried using [UIImage imageWithContentsOfFile:] instead of [UIImage imageNamed:] to load the image as I am aware that [UIImage imageNamed:] caches the image but this has had no effect.
It seems that the spike in live memory caused when attempting to display the image for the first time is causing a low memory situation and the app is being terminated by the OS.
I'm curious to how I can fix this, and how Apple are dealing with loading large images in the Photos app.
Just for the record I'm using ARC and iOS 5.1.1 with XCode 4.4.1.

Related

App crashes in Retina enabled device with low memory warning But in works perfect in non retina devices

I am developing a cocos2d game which is retina enabled . I have added lots of images in my project for both retina and non retina. Game works fine in simulator [Both retina and non retina], and it also works perfect in non retina devices. But when i run the same in the retina enabled device means it get's crashed without displaying any message. When i test my game with instrument application means it shows low memory warning message like this [http://screencast.com/t/sfRDTELrhomC]. When the app get's crash While running in the retina enabled device it's doesn't show any error message in the console. I am terribly confused with the current state can anyone help me out with this problem.
You are probably using a lot of memory to load images, so the device runs out of memory and kills your application.
I'm guessing you are using PNGs (since you didn't give any info on this); when you load an image from PNG, JPG, etc., the image is loaded into memory twice, since it has to be "translated" by cocos into a texture. Also, texture sizes for this operation has to be a power of 2, so an image of 150x150 would take the memory of an image of 256x256. This is a lot of wasted memory.
My first suggestion is to buy Texture Packer (I'm in no way affiliated with them, it's just a great piece of software), which takes your images and makes them into a compressed PVR sprite sheets that contain several images in one texture.
PVR files are loaded directly into a texture, so they don't use double memory, and since they are sprite sheets, you have less wasted pixels.
My second suggestion is to, when loading your images, not do it all in the same tick of the runloop; Cocos uses a lot of autoreleases, and that memory is not cleared until the end of the tick, so instead of loading all images into memory in the same method at once, schedule that method to be called several times and load a new file every time.

Not including non-retina display images in an iPhone project

I have an iPhone Xcode project that currently only contains images for retina display (twice the size as normal and with a #2x.png suffix). When I run the app on the iPhone Simulator (non retina) the images are still being displayed. Does this mean I don't need to worry about including two sets of images: retina and non-retina?
This all seems a bit odd. I would assume that no images would appear on a non retina device if there are no non-#2x files included.
Note: I have not tested my app on a non retina device. Just the simulator.
I'm pretty sure that iOS will just use the #2x and scale it down if you don't have a non-retina graphic. Although that's sub-optimal since you're letting iOS do the scaling at runtime which will be slower than including the non-retina graphic and also iOS might not do as good a job as scaling as your graphics editor of choice.
Even if it works, it's not good practice, and if you have a media heavy app definitely it would impact performance and battery life and memory foot print and ....
By the way, is it just that you don't have the 1x graphics available to you or you are concerned about your apps (download size) or ...
If you are assigning the images in Interface Builder, and you set the image property on a UIImageView to image#2x.png, for example, iOS will not know that it's a high resolution "2x" image. In fact, on a retina display, iOS will look for an image named image#2x#2x.png. Since it won't find it, it will set the scale factor of the image to 1.0.
The contentMode property (just "mode" in XCode) will decide if any scaling of the image occurs to fit the constraints of the UIImageView. You may wish to set the mode to "Aspect Fit" to get the high resolution image to scale as needed for both retina and non-retina displays. In general, the image will display as seen in Interface Builder.
If you are using UIImage's imageNamed or similar function to load the image, and just specify image (where "image.png" doesn't exist, but "image#2x.png" does), then iOS will actually find the image on a non-retina display, though the scale factor will be 1.0. As previously, you'll need to scale it to fit your view. The image will work normally on a retina device, and the scale factor will be set to 2.0, since iOS looks for a "2x" image first, and it doesn't matter if the other file exists or not.
This is from Apple's documentation on imageNamed:
On a device running iOS 4 or later, the behavior is identical if the
device’s screen has a scale of 1.0. If the screen has a scale of 2.0,
this method first searches for an image file with the same filename
with an #2x suffix appended to it. For example, if the file’s name is
button, it first searches for button#2x. If it finds a 2x, it loads
that image and sets the scale property of the returned UIImage object
to 2.0. Otherwise, it loads the unmodified filename and sets the scale
property to 1.0. See iOS App Programming Guide for more information on
supporting images with different scale factors.
If at all possible, you really should include both retina and non-retina images. Using higher-resolution images than necessary negatively affects memory and performance.

iPhone memory warning for high resolution images

I have an app which display images in full Screen. Some of the images are 1952x3680 pixels and these images are raising memory warning level=1 and level=2.
How should i handle these image?
Scale your images down considerably. There is absolutely no reason you need images at that resolution in an iPhone app.
Don't use them. Either get your server to deliver a thumbnail version of the image (maybe using a thumb.php/jsp/asp/... file with GET params x=<width>&y=<height>), or scale the image down on the iPhone and discard the original data. The former method is vastly preferred as it saves on both bandwidth and large memory allocations client-side.
The largest images you should be working with are 480x320 (iPhone 3GS and earlier) and 960x640 (iPhone 4).
EDIT: The other situation I didn't think of is if you're bundling these images with the app. Please, please don't do that. If you have images that big, scale them down in Apple's Preview or any image editor to the sizes noted, and ideally have two copies, image.png and image#2x.png which are shown depending on the scale of the device's screen.
The screen itself is only 320x460 (not considering the clock bar on top), and 640x960 for retina display. There is no reason to have images this large to begin with. Scale them down. It'll both prevent the memory warnings and stymie unnecessary image size.
As said before, scale it down if you only want to show the image without zooming in fullscreen.
If you need to zoom and show it detailed, google for CATiledLayer. There are good examples around.

How to handle loading multiple images for the purpose of scrolling and zooming? Does DPI of an image affects the way an iPad is going to load it?

I am currently working on an image gallery for iPad. As of now there are about 100 images and the count may increase further. The images I am using are of the resolution 2134x1602 # 300dpi. Now with ~2.5MB, i have lost the smoothness in scrolling the images to next image. Also I want to zoom the image up to 8X. The images I am using are all PNG type.
The app works fine in the simulator but crashes bad on the device. Instruments show no leaks and no bad allocations too. It must be some Internal memory issue for sure since the gdb reports memory warning while running on the device. I would like to tell you that I am lazily loading the images.
Can anyone help me with this issue and the strategy i should use to get rid of the slow loading and scrolling. Also I'll be glad if you let me know how an iPad's GPU processes the images it wants to load. Also i would like to cite that changing DPI didn't work out well.
Eagerly waiting for some help.
Thank You.
Your app is crashing because you are running out of memory.
What you will need to do is scale/tile the images. Have a look at how Google Maps works in a web browser on a normal PC, you will need to do something like this. The screen resolution on the iPad is 1024x768 pixels, so there's no point loading more than that amount of data at any one time. When displaying your image at > 0.5x scale, tile it into sections that are max 1024x1024, pre-scaled. Cache everything to disk. When displaying your image at < 0.5x scale, consider having thumbnails at different resolutions. In between different resolutions, do an alpha blend of two images of different scales: eg for scale 0.75x, do a 50% blend of four tiled scale 0.5x images and one scale 1.0x image.

iphone photo maximum size

i want to know there a limitation in size for an iphone to display an image? as the resolution of iphone is 320*480 px. i am developing an app which fetches photos from an URL and that URL contains some photos os size > 600KB.So when i launch the app in simulator it behaves properly but in device the application crashes as soon as photos with higher resolution are displayed , and when lower resolution photos are displayed the app does not crash in the device.
From Apple's doc:
You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer. This size restriction does not apply if you are performing code-based manipulations, such as resizing an image larger than 1024 x 1024 pixels by drawing it to a bitmap-backed graphics context. In fact, you may need to resize an image in this manner (or break it into several smaller images) in order to draw it to one of your views.