blurred #2x images and ios web service data - ios

Why do #2x images get blurry when they have web service data over them?
Web service data looks pixelated too.
Thanks a lot!

You mean, that you are retrieving the image from a webservice? If so, it has nothing to see with a name convention. Images retrieved from a WS must be resized to a proper size. Or just add a parameter to your WS where you can select the size for your image.
The #2x parameter only work for bundled images. If you are downloading them, that won't work.

in your image view try to do not use "Scale to fill" nor "Aspect Fill/Fit" to check if these external images come in correct resolution. If they look smaller than they should - they get blurred on upscaling. Try to provide better res images and use Aspect Fill/Fit (depending on your needs), they'll get downscaled well in pre-retina displays.

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.

iOS ideal image resolution

I'm having a real hard time understanding this, but let's say I have an iOS app for both iPad and iPhone and I want to download an image from a server and display it in full screen.
I have read that the iPad pro has a resolution of 2732x2048 and if we want to display an image in fullscreen we would need to download the image with this size right? However, I also read that the image should never be over 300KB. I was not able to bring an image with this size under 2MB (I used JPEGmini for example to reduce size).
And I don't think that iPhone user would need to download such a huge image, so my question is: what resolution should my images be on the server and how can I manage to keep them in a rational file size. Also should I upload multiple images for different devices? If so, how many and at what resolutions?
Isn't the problem merely that you are holding incompatible beliefs? This is the belief that is giving you trouble:
I also read that the image should never be over 300KB.
Let go of it.
Clearly it is right to say that the image should be no larger than needed for display. But an image to be shown as a 3x scale image on the iPad pro needs to be 2732x2048. So that's that.
(You could, alternatively, use an image 2/3 of that size and show it as a 2x scale image. It wouldn't look quite as good as the 3x scale image, but it might be acceptable.)
On a smaller device, yes, you should scale down the image in code, so that you are not holding in memory an image larger than needed for display. But in this case, you need the large image for display.

iOS resizableImageWithCapInsets & #2x, #3x images

I am creating a 'chat bubble' using this method, by setting the background image after calling resizableImageWIthCapInsets. However, for this method you need to hardcode the cap insets by pixel, but the pixel size is different for each 1x, 2x, and 3x image size. How do I get around this issue? Is there a way to know which image the device is using (the 1x, 2x, or 3x)?
You don't need to do it in code. Xcode has a special tool for this. Check this link, in the section named "CAN I GET THOSE IMAGES FOR THESE BUTTONS, BUT LONGER?" or here. There are explanations how to use it.
If you use this you can not care if image is ready to display or which resolution you should use.

Do i need to return back the image dimensions for ios in json response?

I've built a website that stores images in 4 different sizes on the file system. It keeps the origional file size, medium, thumb, small image and resizes them as they upload.
We then created the web api to allow us to build the ios/android apps.
while building the apis our overseas developer then asked to provide the image dimensions along with the image file name. it took a lot of work regarding calculating the image sizes and saving them to the database.
{ "imagefilename" : "someimage.jpg", "LargeimageHeight" : "1000",
"LargeimageWidth" : "500", "mediumImageHeight" : "500",
"mediumImageWidth" : "250",
"smallImageHeight" : "100", "smallImageWidth" : "60" }
with the amount of image sections we have in the website made it a task and i want to know if this is really nessesary. Im not an ios developer but not really sure as to why the additioanl dimensions of the image need to be saved and or really needed.
i thought the ios has the image feature (#3x) (#2x) (#3x) ??
or do i use 1 specific folder image size for ios ??
does this always happen in the ios world for images that the code needs to know the image dimensions for the best result?
thanks
If your iOS application show images in flow layout (like pinterest style) you must return image dimensions. Otherwise I don't think its nessesary
Do you need the return the image dimensions:
Short answer: no. You can load the image using UIImage, and call image.size.height and image.size.width.
Long answer: maybe, depending on the interface design of your application, and if every image has different dimensions, it might take a performance toll to load the image into memory before being able to get its size (and probably do autolayout and have it render on screen). You might have issues with scrolling speed, but it will depend on the specific design and requirements.
What is the #2x #3x iOS image feature
iPhone and iPad screens come in different pixel densities (non-retina, retina and the retina iPhone 6+ screen). If you have a local image, stored on the phone, it can preload the image with the right scale automatically, by just providing the base name of the image, if you add the right suffix to each asset like name#2x, etc.
Sadly, it doesn't work the same for remote images see this answer. You will have to check yourself for the scale and load the right image, or load one big file, and let it be resized on the device.
You should consider providing dimensions inside your API response.
Think design:
When you scale your app to have many images at once, or when you distribute your app to multiple devices, you may realize the advantage. Your iphone 4 may end up downloading the image (worse, images) intended for iPhone 6S, and so on. If the reverse is true, it's even scary to think about.
How about the device asking for the image it's best suited for?
As for scaling of images, Bram De Geyter is correct - you can render whatever resides on the device, not fetch the correct one from the server. So having your API giving you the right dimensions is the only solution.
I have described the whole image loading from API approach in my blog here.

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.

Resources