UIButton image pixelated - ios

I can't get my UIButton image to not end up pixelated. The original image is 432X417 and my button size is 18X17. I'm setting up the button in interface builder and setting the content mode to aspect fit.

You absolutely should NOT try to install a 432x417 pixel images into a 18x17 point button.
You should create your image at the target size(s) in an image editor (e.g. Photoshop) and install that into your asset catalog. Remember that for most devices an 18x17 point images will need to be 36x34 pixels for 2x retina, and 54x51 pixels for the #3x scaled needed for the 6+ and 7+ devices.
If the image is a vector PDF then it should scale well, although 18x17 points is quite small and hard to show much detail.

Related

Xcode #2x image suffix not showing as Retina in iOS

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.

Size of image to set as Background image in view controller

I am trying to put a background image on a UIViewController.However i cannot figure out the size needed because the image should support devices from iphone 4s to iPAD...Here are few questions:
1) Should i put those large image on image xcassets on 1x,2x,3x size,if so what should be the size of those images?
2) Or Should i Copy a high resolution image on the bundle itself again if so what should be the size?
We have differnet-2 sizes in assets like here:
(Only for iPhones)
What I found is that, you should opt for first option and 750X1333, 1080X1920 and 1242X2208 should be the 1x,2x and 3x.
You can add more by clicking on tick sign and give sizes like above we give for the iPhones.
Designer will give you proper sizes with respect to resolution to each ipad and iphone
Well it depends on what kind of image you want to display
If it's a solid or pattern image that won't have any different if scaling up / down then I suggest that you put it in image xcassets and use for all supported devices. You should put the largest size image, you can find all screensizes from this: http://iosres.com/
Otherwise, if it's a picture with details like a portrait or food dish, etc. You have to drop it manually with some photo editors like photoshop then add it to xcassets separately for iPhone and iPad
In place of 1x,2x & 3x images take single PDF image and place in image assets it ll fit for all comparability devices.
I think this code will help:
var backGroundImageView :UIImageView! //declare
///set image contentMode in viewDidLoad()
self.backGroundImageView.contentMode = .scaleToFill
However, you should check whether the image is in landscape or portrait orientation.
Image xcassets on #1x,#2x,#3x size will match iPhone 4S screen size automatically, #2x is for the iPhone 5, #3x for the Plus.
As for the iPad you can check the Apple Developers documents.

image background files for iPhones

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.

UIButton and #3x images (using Image Assets)

I've got a problem here and it's easy to explain:
I'm using image assets for a new project being built in Swift 2.0 and Xcode 7.1.
I have a bunch of buttons with images set. The buttons are much larger than the images and so they center (as expected) just fine on any #1x or #2x screens.
However, as soon as I build to the 6+ with its #3x resolution, the button instead uses the dimensions larger than the #1x image and the image in the center of the button becomes larger.
So I have an image that's 20x20, 40x40 (for #2x), and 60x60 (#3x).
If I build to an iPhone 6, the image dimensions are indeed 20x20 and the #2x image is used for the double resolution. But if I build to the 6+, the image dimensions are made larger. I don't know exactly how much larger but it's larger than 20x20. This is only happening with UIButton.
Any help is appreciated.
Turns out it was because I was rendering the images at 4x instead of 3x.

Using Non-Retina UIImage for Retina display device

When i started working on my game app i didn't know i should create retina/non-retina #2x, #3x, #1x images. I just created the images with no #1x, #2x, #3x at the end of png file. So since my images are currently called image.png, it's considered a non-retina image i know now. Example is I made an image 25x35 in png. In Storyboards i decided to resize the image and i made it 35x40 because it looks better for iPhone5 than 25x35. My issue is even for 1x i'd have to re-create 40 images from scratch for #3x first and then use Prepo app to automatically downsize to #2x #1x scales. I tested my non-retina images on iPhone 4s/5/5s/6/6+ simulators and iPad 2, Air, Retina simulators and they all look the same and great, and app works well. No blurs or issues. Can I just use my image.png for Retina device as well? Would Apple allow this?
If this is an in-app image, and not the application icon, then yes, you can just use Any resolution image. You can use UIImageView and set contentMode on it to perform AspectFit, ensuring the image will be the same size on every screen type, and also will not get stretched.
myImageView.contentMode = UIViewContentModeScaleAspectFit;
Example: The simplest way to resize an UIImage?
This will preserve the aspect ratio of the image when fitting it to the image view container.
I would provide the image itself with the highest resolution required (#3x), but without #3x in the name, and let UIImageView scale it down to the required size for the other two resolutions.
There is a performance hit in doing this. If it doesn't degrade your scroll performance, go for it.
So basically: start with a high res image and scale down. Do not scale up a low res image, because it won't look crisp. And keep the same aspect ratio so it doesn't stretch.
You will not get rejected for doing this to in-app images.
If all of your assets have the #3x postfix then the App Store recognizes your app as being optimized for the iPhone 6 (together with correctly sized startup images or .xib / .storyboard). Using bigger images for non-retina or normal retina screen causes your RAM usage to increase and slightly taxes your GPU more but for simple apps this isn't a real concern.

Resources