iOS - One Vector Image for All iPhone Resolutions - ios

I am trying to create one vector image for all screen sizes of iPhones. I created pdf file using Illustrator with size for iPhone 6 plus i.e. 1242*231 (231 is my required height of image) and Included it in image assets and changed scaling factor to Single Vector.
Now it is being displayed in iPhone 6 plus with no problem. But when i try the same Single Vector Image in iPhone 6 it is squeezed.
I found out on web that pdf image is converted to #2x and 1#x automatically. like if i have 300*300#3x it is converted to 200*200 and 100*100.
According to this then it is the right behavior because 1242/2 = 621 and it required 750 to display accurately.
But my question is that wasn't the vector image suppose to adjust it? Any other work around this problem?

Try to save it in svg format, this would be better solution.

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.

What is the correct procedure to create images/sprite for iPhone/iPad apps/games?

I am new in developing games with Xcode for iPhone/iPad. Thus I need some help with the correct procedure to create images/sprites for the game.
By now I have created my sprites with Illustrator and I exported them as PDF files. In Xcode I created this single scale asset and put the PDF in it.
If I understand the documentation correctly, Xcode automatically generates image files at #1x, #2x and #3x from the PDF. Does it generate PNG files?
Then I create a SKSpriteNode and set the size like this: abc.size = CGSize(width: 123, height: 123). Instead of 123, I fill in the width and height corresponding to the frame/image size I set up in Illustrator. Is this correct? I think so, because this is #1x version?!
But if I need the same image for iPhone and iPad in different sizes, i can't simply resize it, because the #1x image version isn't a vector anymore and bounded to the frame size I chose in Illustrator? What to do then? Do I have to resize my image in Illustrator and export it in a different size?
What is the correct procedure? Do I have to draw a sketch with pencil at the very beginning on a paper and the measure it with ruler? Then I would go to illustrator and set the frame width height at that what I measured manually?
So many questions. I am very confused with this images sizes, resolutions and #1x, #2x and #3x version. I am not sure why I should use vector files, if I still can't resize the images in the developing process as I would like to, because they are still bound to the frame size I chose in Illustrator.
Is there no possibility to set ratios between all my images and then just use the vector PDF file? How should I setup my Illustrator?
I hope somebody can bring some light into the dark. Thank you.
Your pdf should be sized in points #1x (not pixels). The points should be the same physical size on the phone and the ipad, but if you want them smaller on the phone you need a second set of images; the asset catalog lets you swap out images based on iphone/ipad. Xcode renders your pdf to png's #1x, #2x and #3x and your app will pick the correct png based on the resolution of the device. You are correct that these are no longer vector assets and that scaling them up could leave you with blurry/pixelated images. You have a couple of choices:
1) include a scaled up version of your image at its maximum scale in app and use this version only when you need to scale up (otherwise its a waste of memory and processing if you are always rendering a much smaller image). This is probably the easiest solution.
2) leave your assets as vectors and load them as vectors, You still can render them to images for performance at a constant scale or range of scales, but you can always re-render them at any scale if needed. Most likely you want to use an SVG library for this.
3) You can directly import your assets as code using a program such as paint code. There used to be similar plugins for illustrator but I haven't seen one for Swift 3/Illustrator CC. This is obviously faster than #2 since there is no need to decode the vector file. If your file has a lot of overdraw you may still want to rasterize to images for performance.
Here's what I've found from my experience:
1) Xcode does not generate #2x and #3x from .png files. It can't really - you need to manually supply #1x, #2x, and #3x sizes.
2) Whatever size you use for the CGSize(...), that should be your #1x image, then generate #2x, and #3x from that. I started by designing the size of a level in the scene editor, then made a generic SKSpriteNode shape just to get the size I wanted, then I started making the image from the size I found that looks good.
3) Xcode supports vector based graphics (svg, pdf), but you can't use them as part of a texture atlas, which makes them much less useful in my opinion.

Understanding Image Size for Different Resolution Screens

I'm having a hard time putting all the information on image sizes for #1x, #2x, and #3x together. I've been using the scene editor in XCode with the scene size being 1334x750 (pixel dimensions of the screen of the iPhone 6). So when I size an image for a sprite in that scene, is that the size I should use for the #2x?
From what I've read in the documentation CGSize uses points, not pixels, so if I have an image that is CGSize(width: 50, height: 50), is this independent of my scene size in the scene editor?
Bottom line question: How does the CGSize dimensions translate to how I export my images for #1x, #2x, and #3x in pixels and what should the PPI be when I export?
Xcode can handle vector images, so you can forget about #2X and #3X images if you are able to export your images as PDF e.g. in Sketches export panel one of the options for export format is PDF, so create your artwork #1X and export as PDF, then in Xcode when you add the image to Assets.xcassets, you can set the images Scales attribute to Single Scale. Xcode will generate the required #2X and #3X images from your vector PDF at build time.
The concept is simple. The size in Storyboard or Interface Builder should be the size of you asset in #1x format.
The retina display ( or the iPhone 6+ #3x size ) does not mean than you have much space than before, it means that you can draw 2 ( or 3 ) pixels where you draw 1 before.
So for a 50x50 px Image View, cou should have 3 assets :
- Image#1x.png ( 50x50 px)
- Image#2x.png ( 100x100 px)
- Image#3x.png ( 150x150 px)
Suppose you have created an image in your assets library consisting of 3 sets of same image, #1x.png having size 50x50 pixels, #2x.png of size 100x100 pixels and #3x.png size 150x150 pixels.
you don't needs to worry about which one to use in your storyboard(because storyboard automatically using #1x.png), and which one to use for the targeted device like as iPhone6, or iphone7, or iPad(because by default programing all hardware finds out their pixels relative required image among those #1x.png, #2x.png and #3x.png)
for further instructions you needs to study Auto layout Programing Guide
you can also view their apple's tutorial videos regarding Auto layout.
mysteries of auto layout part1
mysteries of auto layout part2
#1x and #2x used to relate to the retina graphics change when iPhone 4 came out.
iPhone 3GS was 320x480, iPhone 4 was 640x960. This meant that the points per inch were literally the same, but the ppi was doubled, hence the #2x. When the iPhone 5 came out, the only thing that changed was the height, so the ppi was the same for the width, no problems here.
Then we hit the 6 and 6+. At this point, apple said screw it, try to keep ppi that correlate to previous iPhones without having keep the previous iphones usable area, or provide bigger screen pixels for bigger devices. Now #2x has lost its original meaning
But, to really throw us off, they made the iPhone SE, which went back to the ppi screen size of the iPhone 5, so #2x makes sense again.
Basically, when thinking of the #2x graphics, think about the 1st iPhone resolution size.
Now, you have a choice to make. You can give your apps more/less usable area, you can black box the extra usable area, or you can scale and take some kind of quality loss due to game pixels not being 1:1 with the screen pixels anymore.

How images are used from xcassets?

I am having icons for the app stored in xcassets for all 3 versions (#1x,#2x and #3x).
Size of an Asset: { #1x: 28, #2x: 56, #3x: 84}
But when I was trying to read the image size of one of the xcasset item in iPhone6, it showed me 28, which is the size of image to be loaded on iPhone4. I wish to know, if this is the behaviour of iOS or something's wrong on my side.
Thanks in Advance
May be you have put wrong asset in #3x place in your xcasset
and also There is one tool : AVXCassets Generator with which you can directly generate XCAssets file for all your icons and images just by one click.
UI Measurements in UIKit are performed in points instead of pixels. For example, retina screen have 4 pixels per one point, so if you try to read the size of your image at iPhone 5 for example you will get 28 points. On iPhone 6(s) Plus screen is even denser and thats why there is requirement for #3x images.

How do you resize a PNG without losing clarity and sharpness?

I need a few icons for my navigation and tab bars on Xcode 6, so I downloaded a few icons from:
https://icons8.com/web-app/new-icons/all
Yet once I download them and open the file, every size seems pixelated and not as clear cut and sharp as it looks on the actual website.
Why is that? What would be a method to download it just as how it looks and resize it to use it for iOS mobile application? Any insight or help would be appreciated.
Try placing them in the 2x or 3x size in your .xcassets
The 1x size is equal to the amount points on your screen (not pixels). The iPhone 3GS has 320 points in the width so the amount pixels are also 320. The iPhone 4 which has a Retina display also has 320 points, but the actual pixels are 640. So retina needs 2x and the image file needs to be 2 times larger than you expect them in points on your screen. Same for 3x.
I usually work with vectors, you can use them in Xcode as .pdf file, you can scale them as you like without getting blurried images.

Resources