I am making an application which I would like to use the same image for multiple dimensions without stretching or cropping the image.
Can I make different images each supporting a dimension?
You can use contentMode as UIViewContentModeScaleAspectFit of UIImageView's Property.
It will be fit to your imageView, and will not be stretching or cropping.
It will mainain aspect ratio of image.
i.e
imgDevider.contentMode = UIViewContentModeScaleAspectFit;
If you want to prevent stretching, you would have to create a different image for all supported iOS dimensions. Then, using your code, choose the correct image source according to the device's dimension.
Read here about getting the device dimensions.
Read here about changing the image source.
Related
I was trying to put an image in UIButton and the image would fill up the space keeping the aspect ratio intact. I was not able to apply the content mode. Please see the screenshot
I also tried from the code and it's not working as well
myButton.imageView?.contentMode = .scaleAspectFill
By changing the alignment, the image takes the whole space but it does not keep the aspect ratio and content mode does not work as well.
What's causing your problem is how small the image is. There are two things you can do. One option is to set the image you have now as the background image and then change the button's constraints to get the proportions right. You won't be able to have the button be the size you have it now, though, because the image will be all stretched out.
The other thing you could do is find a bigger or different image of that symbol (square.and.arrow), rather than using the one already loaded into Xcode.
I am having difficulties with retina images.
The screenshot below shows the UICollectionView with a UIImageView contained within each UICollectionViewCell.
Within the app I have a large image 512x512 pixels called travel.png.
The green circle shows what is displayed on the app when I name this file: travel.png. The blue circle shows what I see when I update the image name to be travel#2x.png (i.e. retina naming).
I was hoping due to the large size of the image (512x512) that simply adding the #2x suffix would be enough to convert it to twice the definition (i.e. retina) but as you can see from the two screenshots, both version images show as non-retina.
How can I update the image so that it will display in retina?
travel.png:
travel#2x.png:
* Updated *
Following request in comments below:
I load this image by calling the following function:
// Note - when this method is called: contentMode is set to .scaleAspectFit & imageName is "travel"
public func setImageName(imageName: String, contentMode: ContentMode) {
self.contentMode = contentMode
if let image = UIImage(named: imageName) {
self.image = image
}
}
Here is how the image appears in Xcode before the app renders it (as you can see it is high enough definition):
The reason why you see the low quality image is anti-aliasing. When you provide images bigger then an actual frame of UIImageView (scaleAspectFit mode) the system will automatically downscale them. During scaling some anti-aliasing effects can be added at curve shapes. To avoid the effect you should provide the exact image size you want to display on the screen.
To detect if UIImageView autoscale the image you can switch on Debug->Color Misaligned Images at Simulator menu:
Now all scaled images will highlight at simulator with yellow color. Each highlighted image may have anti-aliasing artifacts and affect CPU usage for scaling algorithms:
To resolve the issue you should use exact sizes. So the system will use them directly without any additional calculations. For example, if your button have 80x80px size you should add three images to assert catalog with following sizes and dpi: 80x80px (72 dpi), 160x160px (144 dpi) and 240x240px (216 dpi):
Now the image will be drawn at the screen without downscaling with much better visual quality:
If your intention is to have just one image for all the sizes, I would suggest it having under Assets.xcassets. It is easy to create the folder structures and manage media assets here.
Steps
On clicking + icon, you will displayed a list of actions. Choose to create a New folder.
Choosing the new folder that is created, click on the + icon again and click on New Image Set.
Choose the imageset. And choose the attributes inspector.
Select Single Scale, under Scales.
Drag and drop the image.
Rename the image name and folder names as you wish.
Now you can use this image using the image name for all the screen sizes.
TL;DR;
Change the view layer's minificationFilter to .trilinear
imageView.layer.minificationFilter = .trilinear
as illustrated by the device screenshot below
As Anton's answer correctly pointed out, the aliasing effet you observe is caused by the large difference in dimensions between the source image and the image view it's displayed in. Adding the #2x suffix won't change anything if you do not change the dimensions of the source image itself.
That said there is an easy way to improve the situation without resizing the original image: CALayer offers some control over the method used by the graphics back-end to resize images : minificationFilter and magnificationFilter. The first one is relevant in your case since the image size is being reduced. The default value is CALayerContentsFilter.linear, just switch to .trilinear for a much better result (more info on those wikipedia pages). This will require more GPU power (thus battery), especially if you apply it on many images.
You should really consider resizing the images before displaying them, either statically or at run-time (and maybe cache the resized versions). In addition to the bad visual quality, using such large images in quantities in your UI will decrease performance and waste lots of memory, leading to potentially other issues.
I have fixed, #DarshanKunjadiya issue.
Make sure (if you are already using assets):
Make sure images are not un-assigned
Now use images in storyboard or code without extensions. (e.g. "image" NOT "image.png")
If you are not using images from assets, move them to assets.
Demo Projects
Hope it helps.
Let me know of your feedback.
I think images without the #2x and #3x are rendered for devices with low resolutions (like the iphone 4 an 3G).
The solution I think is to always use the .xcassets file or to add the #2x or #3X in the names of your images.
In iOS, content is placed on the screen based on the iOS coordinate system. for displaying an image on a standard resolution system having 1:1 pixel density we should supply image at #1x resolution. for higher resolution displays the pixel density will be a scale factor of 2.0, 3.0 which refers in the iOS system as #2x and #3x respectively. That is high-resolution displays demands images with higher density.
For example, if you want to display an image of size 128x128 in standard resolution. You have to supply the #2x and #3x size image of the same. ie., 256x256 at #2x version and 384x384 image at #3x version.
In the following screenshot, I have supplied an image of size 256x256 for 2x version to display a 128x128 pixel image in iPhone 6s. iPhone 6s render images at #2x size. Using the three version of images such as 1x, 2x and 3x with asset catalogue will resolve your issues. So the iPhone will automatically render the correct sized image automatically with the screen resolution.
We have a background image for our app that needs to be full screen for each device we run the app on. Our problem is the background image is tiling on our iPhone 6S+ (Display Zoom off).
I have drawn in red lines to highlight where the tiling is occurring...
We have created 3 background images of the following sizes...
So, designing for 1x (which is the recommended way to go), our base level 1x background image is 320 pixels wide. Our 2x is 640 pixels, and our 3x is 960 pixels.
The problem is the iPhone 6S+ is 1080 pixels wide and according to this chart, you need to start with a 3x image that is 1242 pixels wide. And this is where I am missing how this is supposed to work.
from https://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
With the above chart in mind, it seems you need a separate image for each resolution highlighted with a red square in the above image. Is this correct? And if yes, how do you label each individual image so that at runtime the correct one is picked?
Three images, named as you have them for background.png, are all you need.
Now let's talk about image views. They display their image using a content mode. The key thing is to pick the correct mode. Aspect Fill is what you probably want here, because it will fill the image view without distorting the image.
One procedure, then, is to use a bigger image than what you have, and configure the image view that shows the image to use an appropriate content mode such as Aspect Fill, so that it sizes the image down to fit (or, to save memory, at runtime you can size it down yourself).
The other possibility would be to leave your image as it is, and solve the issue on the Plus machines by telling the image view to size the image up to fit, again possibly by using Aspect Fill. That might or might not look acceptable; you'd have to try it and see what you think.
I have a very simple requirement here but I'm looking for a solution for a while. I want to take a profile picture form the camera roll or camera and display it in two different image views (different sizes). I don't want any of these images stretched or miss any part of the image. If I use aspect to fit, top side of image is cut from smaller image view and some parts missing on the bigger image view. If I set it as scale to fit, it will get stretched!
I'm not sure how some mobile apps work. Do they save different image sizes in their server or they change the size of the image. I saw many posts how to change image size without changing aspect ratio. But I don't think it is possible to avoid stretched effects. I used some of those code to change size of image, it gets stretched all the time.
Is there any way to save the image from camera roll one time with size of 140*200 and one time 160*200? So I can use 140*200 for image views that size. But what if I have different devices and different sizes.
I am displaying image thumbnails from urls(which are in json file) into custom cells of a tableview.
The images loaded from url are not showing up properly- they are of a resolution much higher than need and some are of much lower resolution.
How do I manipulate these images so that they are scaled properly as per each screen(retina as well as normal) in iphone?
How do I scale and resize the thumbnail images from url?
Unless you care about other issues like memory or disk usage (for some caching) for the images, you don't have to resize them.
You can use UIViewContentModeScaleAspectFit as contentMode for an UIImageView and just set an image for the image view. It would be sufficient for you.