I have an image that I would like to display in my iOS app. To conserve memory, I would like to display the lowest possible resolution that still matches the number of physical pixels on the device
For example, could be displayed as a square 1/4 the height of the device. So the sizes would be as follows
iPhone 4s 240x240 px
iPhone 5/5s 284x284 px
iPhone 6 334x334 px
iPhone 6+ 480x480 px
I've looked into asset catalogs, but I don't see any way to have a different image for iPhone 4s, iPhone 5/5s, and iPhone 6 (they are #2x). The only difference is iPhone 6+ (#3x).
I've also tried adding the Retina 4 2x option, but that only gives a different icon for the iPhone 5/5s - there is still no way to differentiate between 4s and 6.
I understand that I could choose the image programmatically based on the device, but asset catalogs only downloads the necessary images to the users device (not sure if that is true, I remember reading something about it, though), making the application take up less storage. It would be inefficient to include four images, if only one will be used.
Is there any way to use a different image resolution for every iOS device with a different amount of physical pixels?
Note that I'm not asking about scaling the image, but about getting the correct resolution used (a different image for every device), so less RAM will be taken when it is displayed.
I ended up just creating a different file for every device, and naming them imageName#size, so for an image of a dog that is 128x128, the file would be named dog#128.
Here's the code that I used to do this
func getPNGImageForSize(size: Float, named: String) -> UIImage?{
//the image size will be measured in points, which is the unit that is used
//when setting the frames of UIViews. To turn this into pixels, it must be
//multiplied by the screen's render scale (on an iPhone 6+, 1 point is equal
//to 3 pixels, or 9 pixels in 2 dimensions (3^2).
let scaled: Int = Int(ceil(size * Float(UIScreen.mainScreen().scale))
let imageName: String = "\(named)#\(scaled)"
//ofType set to png, because this image is a PNG
let path = NSBundle.mainBundle().pathForResource(imageName, ofType: "png")
return UIImage(contentsOfFile: (path ?? ""))
}
And to call it, I simply use
getPNGImageForSize(Float(self.view.frame.height / 4), named: "dog")
which would result in the following images, depending on the device
iPhone 4s dog#240.png
iPhone 5/5s dog#284.png
iPhone 6 dog#334.png
iPhone 6+ dog#480.png
This could also be altered to work with non-square images, named imageName#width-height
func getPNGImageForSize(width: Float, height: Float, named: String) -> UIImage?{
let scaledWidth: Int = Int(ceil(width * Float(UIScreen.mainScreen().scale))
let scaledHeight: Int = Int(ceil(height * Float(UIScreen.mainScreen().scale))
let imageName: String = "\(named)#\(width)-\(height)"
let path = NSBundle.mainBundle().pathForResource(imageName, ofType: "png")
return UIImage(contentsOfFile: (path ?? ""))
}
You need to set your image as to what it may look like in iPhone6+ which will consume the #3x images, then scale down to its #2x image size which will be consumed by iPhone4S to iPhone6 devices and then further scale your image to #1x which earlier versions of iPad devices use.
Create 3 different images with 3 scales of #1x #2x and #3x.
there are 3 only, Older iPhone - 3S, 4, non retina iPad all consume #1x images, whereas iPad Air, iPad retina , iPhone 4S - iPhone 6 uses #2x and iPhone 6+ uses #3x
FYI
I have answered this question before here is the link
Here is another good blog about image scaling in IOS devices (all of them)
EDIT
and about clearing your doubt about how come iPhone5 and 6 use #2x images.
Well iPhone5 uses the same image that is for iPhone6 i.e #2x images despite of the height as iPhone5 scales down #2x into its own limit hence there is nothing to worry about this. Xcode takes care of this quite efficiently.
Related
I have already added all images in three format like test.png, test#2x.png, test#3x.png for IOS in resources folder, still on big resolution screen like ipad it shows default one test.png.
I am not getting why this is happening. Am I missing something from code side.
EDIT :
sorry my mistake. my question was wrong.it shows different image but in small size.
i tried 3 different images with same name having #2x,#3x extension. so i come to know that in ipadPro(9.7 inch) it shows #3x image while in iphone5(which lowest screen resolution simulator in my mac) it shows # 2x image.
so how could we decide which screen resolution will take which image?and how can we decide their size.?
Depending on the device, you accomplish this by multiplying the number of pixels in each image by a specific scale factor. A standard resolution image has a scale factor of 1.0 and is referred to as an #1x image. High resolution images have a scale factor of 2.0 or 3.0 and are referred to as #2x and #3x images.
Suppose you have a standard resolution #1x image that’s 100px x 100px, for example. The #2x version of this image would be 200px × 200px. The #3x version would be 300px × 300px.
iPhone X, iPhone 8 Plus, iPhone 7 Plus, and iPhone 6s Plus support 3x
resolution. iPhone 8, iPhone 7, iPhone 6/6s and iPhone 5s/5c support 2x
resolution. All other iPhone devices support 1x resolution.
Consider following sample set of images for view with size 10 points and how do iOS system selects device resolution specific image.
#3x -> 3 * (10px x 10px) = (30px x 30px) // iPhone X, iPhone 8 Plus, iPhone 7 Plus, and iPhone 6s Plus
#2x -> 2 * (10px x 10px) = (20px x 20px) // iPhone 8, iPhone 7, iPhone 6/6s and iPhone 5s/5c
#1x -> 1 * (10px x 10px) = (30px x 30px) // All other iPhone devices
Note: You don't need to do any code (setup) to assign device resolution specific images. Just add images for all (1x, 2x and 3x) types of resolution in your image set. iOS system automatically chooses/selects device resolution specific image from the set of image.
Look at this document of Apple: Image Size and Resolution
Here is nice tutorial for easy understading: DESIGNING FOR THE NEW IPHONE SCREEN RESOLUTIONS
Mostly every iOS application has a view with an image as background. Is there any image sizing guide out there? For example here is an iOS screen designed in Sketch:
As you can see there is a background image. Now there are lots of Apple devices every application should support. The new iOS 10 supports all devices from iPhone 5 to iPhone 6s Plus. They have different screen sizes and resolutions. When creating Xcode assets, I am giving 3 background images with different sizes - #1x, #2x, #3x. What sizes should they be?
The way I see it you have 2 options:
In here you will find the resolutions of the iPhone's:
You don't need the #1 image since you don't support iPhone 4 and 4s (iOS 10).
#2 is for iPhone 5,5c,5S,6 and 6s so basically you can create #2 image of the highest resolution which is the iPhone 6 and this image will work well for the iPhone 5 family.
Or, you can create an image with resolution for each iPhone and using hard coded logic set the image for each phone.
i.e: if iphone5c { setImage("iphone5cImage") } etc etc..
The simplest solution is to create 1 image with the highest resolution. The #3 is the highest for the iPhone 6S+ and it will look amazing for the rest. Don't forget to set the image view as aspect fill.
Also, don't forget to check this thread: How to handle image scale on all the available iPhone resolutions?. It will give you clues of what exactly you are dealing with. TL;DR, It's the options I wrote.
The background images you only need to give are #2x and #3x, because #1x devices are now long gone in the dusty pages of history.
Speaking of #2x and #3x, the image resolutions you give to the developer should be the same with the highest resolution iPhone that uses that given size.
For #2x, that is the iPhone 6, which is 750x1334, and for #3x, the iPhone 6+ which is 1242x2208.
Down-scaling shouldn't be a problem because the aspect ratios of all iPhones that support iOS 10 are the same(16:9).
Note for Developer(s):
The UIImageView will then down-scale the images appropriately,
provided:
1. you created an image set with the provided #2x and #3x images,
2. correctly constrainted the UIImageView to the edges of the superview, and
3. selected the Content Mode of the UIImageView as Scale to Fill or Aspect Fill.
There is design nuance in full size background images. Mostly if the scale aspect fill good enough for different sizes you need to design only for the biggest device size after that the rest of them scale to fit. Sometimes some part of background needs to remain visible or if want to keep a low memory footprint for small device sets you need to create smaller alternatives.
Whenever you make a decision with the design size of asset you need to create #3x,#2x variants.
One more thing I need to point out about vector designs. If your design is made only with vectors you can choose pdf vector export. Storyboards can accept vector assets and they are doing very good when scaling in full backgrounds.
I use background images in my Apps. To solve this problem I use one image that has the resolution to cover all iPhones and all the iPads except the large one.
The image size is 2048x2048 points or 1024x1024 pixels at #2x to cover the 9.7 inch iPad.
The image is compressed JPG to keep the size down. Note that I allow it to scale for iPhone 6 Pluse (#3x) and 12.7 inch iPad Pro (#2x) as the quality doesn't seem to be affected.
I can justify the scaling for the larger devices, because if I provided image for the 12.7 inch iPad Pro, it will be 5464x4096 points (#2x) and 2732x2048 pixels and then the JPG compression would have to be so high (if I wanted to keep the size down), that the quality of the image was low anyway compared with scaling.
If you need high quality try both JPG and PNG for comparison, because the PNG becomes very large for complex images, but gives the best quality.
If you still have the same problem then you can try this one. For this you have to add only one image with good resolution and below code..
UIImage *bgImage = [UIImage imageNamed:#"art_background_star#3x.jpg"];
CGSize screenSize = [UIScreen mainScreen].bounds.size;
UIGraphicsBeginImageContextWithOptions(screenSize, NO, 0.f);
[bgImage drawInRect:CGRectMake(0.f, 0.f, screenSize.width, screenSize.height)];
UIImage * resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIColor *backgroundColor = [UIColor colorWithPatternImage:resultImage];
self.view.backgroundColor = backgroundColor;
There are 3 kinds of Apple Devices (iPhone and iPad) that is
Normal device which terms to 1 pixel = 1 point#1x (Older iPhone and iPad devices)
Retina device which terms to 4 pixels(2 x 2) = 1 point#2x (iPhone 5+)
Retina iPhone6 and iPad which terms to 9 pixels (3 x 3) = 1 point#3x (iPhone6+)
For iOs 10 that will not support iPhone 4s so you only require #2x and #3x images.
As you can see above attached image iPhone 6 also support #2x Scale so use image size for #2x is of 750*1334 and for #3x is of 1242*2208 with image mode.
Take a look at the page on documentation, there is Static Launch Screen Images, and you can catch sizes from there.
You can get a device screen size, using
CGSize screenSize = [UIScreen mainScreen].bounds.size // (Objective-C)
let screenSize: CGSize = UIScreen.mainScreen().bounds.size // (Swift)
And after you can programmatically select an image you want, from set of an images from the bundle. Or to make a big one image for resizing, using knowledges from documentation, and to resize an image accordingly. Or...your choice.
Different "sizes" #2x, #3x is scale.
And here is the nice explanation.
I've a question about resolution of Iphone 6 and Iphone 6 Plus.
I would like to know something about #x2 and #x3, i really need to be sure !
If i've a fullscreen UIImageView, display on a Iphone 6(667x375 points) the size of the containing UIImage have to be 1334x750 because the size in points are 667(#x2)x375(#x2), right?
So if i understand, the UIImageView on Iphone 6Plus in fullscreen is 736x414 but the resolution is #x3 then the UIImage in the UIImageView have to be 2208x1242 because the size in points is 736(#x3)x414(#x3), no ?
Then in a general case, i only need to know what is the size of my UIImageView and if the resolution is #x2 i multiply the size x2 and if the resolution is #x3 multiply the size x3?
Guys i really need a confirmation and if i'm wrong, please, explain me why !
I'm sorry if you think my question is really stupid but i need to understand how it works.
Cordially :)
Lets go for a ride of #1x, #2x and #3x image scaling and content viewer size according to different resolutions in iPhone.
Let understand some basics first
Device Resolution
================================
iPhone 4 & 4S 640×960
iPhone 5, 5C & 5S 640×1136
iPhone 6s 750×1334
iPhone 6P 1242×2208
Resolution reference from this site.
Now if how to use images with #1x, #2x & #3x.
Lets say you have an imageView in with size of 100W x 100H, to display images properly on all the devices with appropriate resolution without stretching or pixelation your image, one need to create 3 set of images as below according to device.
iPad 2, iPad mini supports #1x images, required image of size 100x100(WxH)
iPad, iPad mini supports #2x images, required image of size 200x200(WxH)
iPhone 4S, 5 & 6 supports #2x images, required image of size 200x200(WxH)
iPhone 6P supports #3x images, required image of size 300x300(WxH)
Though your UIImageView size is 100x100 for all the devices, but image displayed in different devices is different according to their resolutions.
Following size Table will give you more clarification, read more about it in apple documentation here
I hope it clears confusion about different resolution images for different devices :)
I'm creating a universal iOS application (supports iPad and iPhone 4 and later). In this application, I have an image that spans the width of the screen on every device (and maintains a constant aspect ratio). In order to be as memory-efficient as possible, I created a version of this image for each device I support, which each version of the image sized to exactly fit on the device it's intended for.
What is the best way to store these images in my Xcode project, and load the correct image in my code?
Right now I just have 2x and 3x image assets for the image (and a 2x for iPad) and load it with the following line of code:
let imageView = UIImageView(image: UIImage(named: "image"))
But that doesn't allow me to have a different image for, say, iPhone 6 and iPhone 5 because they both load the 2x image.
If I'm writing an iPhone app, I have to use "#2x" suffix for devices with retina display and "#-568h#2x" for iPhone 5 apps. How should these images differ? Should I make the image with double length and height (80x40 -> 160x80)? And what about "-568h#2x"? Thank you for help!
Yes, images for retina displays are double the size of normal ones, so as you said, if you have a 80x40 image, the 2x version should be 160x80.
As for the 568, same width but the height you want to appear in a iPhone5 screen. This image is not mandatory, you can use the same image for retina screens for iPhone4 and iPhone5, this is just in case you want to have different ones, for example for the splash screen.