how to deal with big picture in UIScrollView - ios

I have a big picture to show in UIScrollView.It's 28.1 MB.And it often crash the app.Is there some methods to deal with it so that app won't crash?

Here you go buddy,
Convert Large Image to tiles
Displaying tiled images in UIScrollview
Tiled Images in UIScrollView

If it's a static PNG image, run it through ImageAlpha and ImageOptim (Google these). You might be able to get it down by well over 50%. Bundle the resulting image with your app instead.
Note that ImageOptim is lossless whereas ImageAlpha is lossy. You can use them in conjunction.

Split up the image and load the pieces only when necessary.

Related

iOS app crashes because images use too much ram

I know this is a stupid problem, but this is my first real app that I have to make, I have no one to ask and I looked up this problem and found no other similar problems.
My app crashes on real devices with no exception. I saw in the simulator that uses too much RAM and after a while I got to the conclusion that the pictures I am using are to blame.
The app is structured in this way: it has 8 viewControllers for different things: for example, it starts with one which lets the user select the avatar with which he/she will play and here I have two pictures, next is a viewController which shows the stats for that avatar and here it is another picture and so on. The problem is that each picture uses 40MB of RAM to be displayed and things add up so the app uses more than 300MB of RAM when the user gets to the gameviewCOntroller where the game is. Because of this, on devices like iPAD 2 or iphone 4 it crashes, but not on iphone 5.
I tried to set the images both from "images.xcassets" and from a ".atlas" folder, but the result is exactly the same. The pictures have a dimension of no more than 1500x1999px, they are in png format.
Also, I saw that if the app were to start directly into the gaveViewController it would use 180MB so the other viewController remain in memory or something like that. Should I "clear" them or something similar?
//-------update-------
This is what I got from Instruments:
Memory is a big deal on mobile devices, there is not a clear answer to you question, but I can give you some advices:
If your images are plain colors or have symmetric axes use resizable images. You can just use one line of pixel multiplied by with or height to cover the entire screen using a small amount of memory
Image compression doens't have effects when the image is decompressed. So if you have a png that is 600kb and you are thinking that converting in a 300kb will lower memory usage is only true for "disk space" when an image is decompressed in memory the size is widthXheightXNumber_of_channelXbit_for_channel
resize images: if are loading a 2000px square image into memory and you show it inside an image view of 800 px square, resize before adding it.You will have just a peak while resizing, but later it will use less memory
If you need to use big images, use tiling techniques such as CATiledLayer
If you don't need an image anymore get rid of it. It's ok to have an array of path to images, but not an array of full uncompressed images
Avoid -imageNamed it caches images and even if Apple says that this cache is released under memory pressure, you don't have a lot of control on it and it could be too late to avoid a crash
Those are general advices, it's up to you if they fit your requirements.
You should definitely follow Andrea's advices.
Additionally you should consider setting the image size to exactly what your need is. You're saying that you've tried to set them from xcassets so you have full control over the images you're loading, which is great (compared to downloading an image that you cannot modify).
I highly suggest you read some documentation on using Asset catalog files. This will allow you to have high-resolution image for bigger screens that also have more memory, and smaller ones for older devices, which is what you want here.
Also, note that 1500x1999px is still a very big size for most mobile devices.
More links about screen-size:
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
http://www.paintcodeapp.com/news/iphone-6-screens-demystified

jpg or png for user profile pictures?

My app requires that each user has a profile picture of around 140*140px. Right now I am using jpgs, I am wondering if performance wise it will be better to use pngs. I read pngs are good for small UI elements and images, jpg for large images with detail such as photos. Obviously my profile pics are photos but they are small. Would it make much difference switching to png? Thanks
JPEG is best for small file sizes of photos, even for low resolutions.
PNG makes sense when there are many pixels of the exact same color next to each other. This is not the case with photos.
These should be helpful for you.
When to use PNG or JPG in iPhone development?
PNG vs. GIF vs. JPEG vs. SVG - When best to use?
Apple optimizes PNG images that are included in your iPhone app bundle. In fact, the iPhone uses a special encoding in which the color bytes are optimized for the hardware. XCode handles this special encoding for you when you build your project. So, you do see additional benefits to using PNG's on an iPhone other than their size consideration. For this reason it is definitely recommended to use PNG's for any images that appear as part of the interface (in a table view, labels, etc).
As for displaying a full screen image such as a photograph you may still reap benefits with PNG's since they are non-lossy and the visual quality should be better than a JPG not to mention resource usage with decoding the image. You may need to decrease the quality of your JPG's in order to see a real benefit in file size but then you are displaying non-optimal images.
File size is certainly a factor but there are other considerations at play as well when choosing an image format.

What are the ways to reduce bundle size on iOS?

I have some images which are huge in size and my bundle size currently is 70 MB. I think Xcode already runs the assets through png crush.
Do not use any text images with useless effects, use UILabels instead.
Draw simple shapes and effects using CAShapeLayers instead of using
images.
Use JPEGs instead of PNGs where you don't need transparency.
(Actually file size depends on the image content here)
Use Save for Web option in PhotoShop or other tools to optimize PNG
images.
Use sprites combined together instead of separate images.
Make sure you delete all unused resources.
Do not localize common parts of the images, localize only the
different parts. (think of a background image with a small flag at
the bottom for each locale. use one single bg image and separate flag
images. localize flag images only, not the entire bg images with the
flags.)
Use the same splash images for iOS7 and previous iOS versions. (You
need to manually edit the JSON file in .xcassets)
Try using a CDN to download assets on the first launch.
In addition to images keep those in mind too:
Try replacing custom fonts with default system fonts if you don't
need them really.
Use MP3 audio files instead of WAV files. (or other
compressed formats)
Make sure you delete all unused 3rd party frameworks.
You can try converting the images to jpg (if they don't have any transparent regions).
Also try using http://imageoptim.com/
It seems very unlikely that you actually need huge images. After all, the screen is not huge. Thus, the most likely form of size reduction is to reduce the physical dimensions of the images to the size you are actually going to be displaying.
This saves bandwidth when the user downloads the image, reduces the size of the app on the user's hard disk (the device), and also saves memory at the time an image is loaded. It is a vast waste of RAM to load an image that is larger than the size at which it will be displayed; after all, remember, the memory involved rises exponentially with the square of the difference.
One option is to host the images on a CDN like OpenText and fetch them as part of app initialization, or whenever they are first needed. Obviously this is more coding, but projects like SDWebImage make it pretty easy:
https://github.com/rs/SDWebImage/tree/master/SDWebImage
It also gives you the flexibility to swap out those images later if you use caching headers.

Interface building - UIViews vs Images vs Core graphics vs PDF subclass

My app uses flat graphics, which mostly consists of lines and flat surfaces...
Whats the best approach for building the UI?
use PNG images as much as possible (like for the attached picture, the whole background would be an image)
use 4 UIViews (in this example case) with background color to make the background and the 3 lines
use CoreGraphics to actually draw in drawRect (or somewhere else?)?
subclass UIView and draw PDF content
any other approach?
What are the performance impacts? The advantage of the first two, is that they can be done in IB, but is there a downside (like performance or quality or caching)? I also heard of a trend of using CoreGraphics for drawing all the time...
So basically the fastest way is to use PNG files (stretchable and normal), also if you are using PNG files it will be easy to change the design and fix eventual bugs.
When you are using PNG files, try to reduce the size of the PNGs (stretchable images for backgrounds) for a better performance and a small size of the app.
CoreGraphics is more complex and can add strange bugs or performance problems if you don't know what you are doing, but can be use also for simple view styling.
On every project that I've done I couldn't use only one of these two because of the project complexity or because I was to lazy to open photoshop and add extract some designs.
As H2CO3 said is not that simple. Each format suits particular requirements, there are no written laws, I just ca tell you what I do.
Small pieces of UI, such as buttons, icons etc: I normally use PNG or PDF. You can subclass a UIView to draw PDF vector content. The plus with PDF is that if the source is a vector image, you could not take care about physical-logical points.
Images or Hi-res images, such as image of a content: In this case I use JPG, for they small size respect of PNG. They take little bit more to decompress but usually the size is very smaller compared to PNG.
In general PNG can use alpha, JPG no
Image is a big topic, nowadays I always try a way to find symmetry in UI elements and use stretchable UIImages with PNG.
For you example I will use PNG witch stretchable left and right side. Instead of use 640 px image, you can use 10 px image, with stretchable right margin and stretchable left margin.
[update]
It should be said that if you use stretchable images you will get a lot of performance boost, since the image will be smaller, you will occupy less memory on the "disk", less memory on the heap thatnks to the GPU stretching and less decompressing times
.

Use icns file as an image in iOS

Is there a way to use an icns file as the image source for I guess a UIImage? Or pick out one of the representations and resize?
NSImage does not seem to be available in cocoa-touch.
In particular I'd like to use them for drawing in the imageView part of a UITableViewCell.
There is no built-in way to do this and I see little benefit in doing so. It's best to just use the sizes that you need and ship them as individual images in your app. If you want to draw the images in a UITableViewCell, performance is an important aspect and resizing images won't be fast.
If you really need images in many different sizes and really don't want the best performance by including images for each size, you could use a PDF to make use of vector graphics. There is a nice article about this technique: http://mattgemmell.com/2012/02/10/using-pdf-images-in-ios-apps/
Honestly, don't try to use .icns files in your iOS app. It's just a container for images of different sizes and resizing is not a good idea, anyway. Either include individual images for any size you need or use vector graphics using a PDF file.

Resources