Does the size of a placeholder image affect performance? - ios

At the moment I am downloading images remotely using a UIImageView category. While the image is downloading I use a placeholder image that is stored in an xcassets folder.
Is it worth having multiple placeholder images for different sizes: small, medium, and large? Or is it worth having 1 placeholder image and using it throughout the application?
Does the size of a placeholder image affect performance?

Well, you should have #2x and #3x version of the images, as it will mean less work by the CPU to scale up / down the image on different devices. Also, there is technically work done by the CPU to scale an image up or down. However, Apple's graphics processor is pretty efficient at scaling images.
So the technical answer is "Yes, it does affect performance", but in reality it is probably not a big enough difference for you to notice.
Now, if you have built a poorly written app that displays hundreds of these placeholders in a UIScrollView instead of some form of a UICollectionView (which only displays what is on screen, or about to be on screen), you will notice that the slight performance difference for all those images adds up to a large performance difference.

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

What's the best way to use big textures (2048*1536) in Unity3d with NGUI on ios?

I'm using Unity3d (4.3.1) and NGUI for creating an 2d iOS (iPad) app. Also I need to use a lot of full screen images (about 100 images with size 2048x1536), for Gallery for example.
Now I'm using them with GUI type, override for iPhone with max size 2048 and compression quality: normal. And I'm using a UITexture with Unlit/Transparent shader to show them.
However, after about 40 images in the project XCode returns the terminated due to memory error. So the question is, what type of images do I need, and with which preferences to make them work?
I'm using iPad 3 as a test device with XCode 5.1.1. I'll be thankful for any help!
Also I need to use a lot of full screen images (about 100 images with size 2048x1536), for Gallery for example.
I think your 2048x2048 size images use a very huge memory area. Basically, 2048 image use 16MB memory. So, this case need to use about a 1600MB memory! Normal application don't over about 200 MB.
So, I think you need to be reduce using a memory:
Remember that this texture is going to be expand 2048x2048 by unity.( http://www.opengl.org/wiki/NPOT_Texture ) So, if you are going to reduce file size to 1500x1000, your application still use 2048x2048 image. But if you can reduce file size to 1024x1024, do it. 1024 image just use 4 MB memory.
If you can use texture compression. Use it. PVRTC 4 bit ( https://docs.unity3d.com/Documentation/Manual/ReducingFilesize.html ) compression is make file size 1/8 than true color. Also memory size is going to reduce.(maybe reduced to half)
If your application don't display all images, load image dynamically. Use thumb nail.
Good luck:D
If you want to make a gallery-like app to render photos maybe you can try a different approach:
create two large editable textures and fill texels with image data (it must be editable otherwise you will no have access to write directly image data into them).
if you still have memory issues or if you want to use lower memory you can use several smaller textures as tiles. You can render then image parts to each smaller texture. Remember to configurate correctly the texture borders or so not use border texels to avoid wrapping problems.
Best way is to use a smaller texture. In an ipad you will need a magnifying glass to really appreciate the difference between 1024x1024 and larger textures. Remember an ipad screen is smaller (7"~10") than a computer one and with filtering enabled is really hard to tell the difference.
If you still need manager such a large texture for some other reason (zooming or similar) I recommend you one of the following approaches:
split the texture into layers with alpha channel (transparency): usually backgrounds can be rendered with lower resolutions.
split also the texture into blocks: usually most textures have repeating patterns.
use compression.
Always avoid use such large textures if possible.

UIImage size managment

I have an image that is used in multiple places within my IOS app at various sizes. Should I be using one large image in conjunction with UIViewContentModeScaleAspectFit to scale it (currently this approach seems to cause distortion on the smaller images despite being scaled to proportionate sizes) or should I have multiple versions of the image at different sizes.
It seems a little extreme to have so many copies of one image e.g. my_image_ipad, my_image_small, my_image_large, my_image_medium.
In general it depends on what it takes to get the look and quality you want. Some images will scale from a large image to a small image with little or no visual loss in quality. Others, as you've found, scale poorly, especially at extreme scales. You're really going to have to just try various solutions and see what works. One way you can almost always cut down on application size is to remove the non-#2x artwork and ship with just the #2x.
It is better to use one image, because it will make your app "lighter", but this may cause your code to become bigger.

When to use double size images

I was thinking to write some quiz app where questions are represented as images.
My question is, for each quiz question (question.jpg), and thus a jpg file, do I have to create
a double sized question#2x.jpg file?
Is it necessary?
Doing this seems will increase size of my program so I was thinking when/if this is necessary to do?
PS. And in case I have to do it, I will just have to double in size each image manually and add to the project right (both original and double sized image)?
PPS. Just to add more info. The questions are located on the web site, I have to download them and add to my project manually (like resources). On web site there are no different versions of the same image. So, I have whatever is on the web site. Some images I noticed are 800x600 in dimensions but some are also in dimentions 500x400. So after I download these images, how shall I name them? Just with original names? and forget about the #2x extension? What's the best practice?
(if this will help my image view will probably be smth .like 310 in width). Do I have to modify them in size? What to do?
Apple's naming conventions of high resolution images can be found here:
Apple doc naming conventions
If you are developing in the way that you want to support old screen as well as retina screens. You can use xxxx.jpg for old devices as iPhone 3gs and iPad 1, and use xxxx#2x.jpg for retina displays. Where the aspect ratio needs to be the same but the #2x image needs to be twice as big.
In your case "my image view will probably be smth .like 310 in width", then the #2x image needs to be 620px in width and normal revolution 310px.
There is actually no need to have both image sizes in the app as you can use the same image and just scale it(If you really really need to have the old resolution supported).
Even if you add just a #2x, it will scale itself if someone on an old device installs your app. It may become a bit blurry but will still be quite ok.
If you are planning to use a lot of images in your app I suggest using some sort of web service where the user can download content that is to be shown. But that's just me. As the app will quite quickly become very large as images takes up quite a bit of space. Of course this all comes down to how many images you will have.
The drawback of using a web service is that the user much have an internet connection to be able to play. And download your content.(Most quiz apps I know of does use a web service for this.) This is a matter of taste.
If you do need to support normal and #2x here us a method you can use. This method will return the scaled image so you just need the normal one or the #2x one and then scale to the other size. This will at least help you a bit when it comes to getting either your app size down or your clients download time down.
If you are using .jpg's and scaling them upwards you can quite easily get a pixalated image as it is a lossy format. But if that's what you still want to do and maintain aspect ratio, this is one way to do it:
-(UIImage*)resizeImage: (UIImage *)imageToScale withScale:(CGFloat)theScale{
UIImage *image = [UIImage imageWithCGImage:[imageToScale CGImage]
scale:(imageToScale.scale * theScale)
orientation:(imageToScale.imageOrientation)];
return image;
}
Usage
[self resizeImage:[UIImage imageNamed:#"question.jpg"] withScale:0.5];
0.5 would double the size and 2.0 results in an image half the size as the original.
If you want a more complex method to set for instance set a specific target size just say so and I'll edit this answer.

iOS: #2x - does it mean anything besides twice the size?

Silly question. But regarding images for iOS, I keep seeing the #2x identifier. Does that just mean the image is twice the size and therefore clearer as opposed to "#1x" image with the same dimensions? Or does the #2x actually mean something when compiling. What's the drawback to just using larger images and scaling them down inside xcode?
Clearly I don't understand something.
#2x is just the convention Apple chose for what image to use on a retina device vs a non-retina one—it has no meaning for compilation.
Using larger images and scaling them down doesn't look as good as using 1x images (you can try it yourself). Sometimes a designer might also e.g. remove details from a 1x image because at the lower resolution you can't make them out. Some things also don't scale down well, such as 1px lines. Scaling down images also adds overhead in I/O (opening a larger file) and at runtime (scaling algorithm).
Technically the #2x doesn't even need to be double the size of the 1x, though it's rare that you wouldn't want to do that (in one case for me, I was using resizable images and it was more convenient to have their cap-insets be exactly double even if the images themselves weren't).

Resources