I'm trying to programmatically adapt my website's image sizes for differently sized devices. But now I am having trouble telling what sizes I actually need. In Google Chrome emulator, I'm seeing some of my images upsized, e.g. on iPhone 6 from 230x230 natural to 357x357 displayed. The image takes up nearly the entire width of the emulated screen, and looks just slightly degraded, suggesting iPhone 6's width isn't much larger than 357 pixels.
But Apple says the iPhone 6 has a resolution of 750x1334! If that were true, the image should look much worse, I would think.
I've found some contradictory information on iPhone 4 as well.
This site talks about iPhone 4 at 640x960 pixels. Chrome emulator again shows it at half those dimensions, 320x480.
This stackoverflow question says that "the iPhone screen is 320x480 definitely."
What am I missing here? Why do some sources (including Apple) supply dimensions that are twice what Chrome emulator (and my images) say?
Relax, you're about to understand this mess. Just notice that 2 * 375x667 = 750x1334.
A pixel is not a pixel
The key thing is: one device pixel is different from one CSS pixel.
They are the same in low pixel density devices like your computer screen (96 dpi). However, high pixel density devices like smartphones and printers (upwards of 160 dpi) try to obey the general W3C CSS3 spec understanding that one CSS pixel should always be close to 1/96th of an inch (or 0.26 mm) when viewed from usual distance (arm's length).
They don't obey the spec to the letter, since that would imply 1px being exactly 1/96th of one real inch in high DPI settings, which wasn't ever implemented in any browser AFAIK. However, they try to make their CSS pixels not so minuscule despite very high pixel densities by making one CSS pixel equal to two or more device pixels.
Chrome Device Mode works with CSS pixels, which is what you should use to design text, navbars, headings etc, but not high-resolution images. For these, read the next section.
If you didn't notice, the image above shows that Chrome Device Mode does show you the device scale (how many device pixels equal one CSS pixel).
Fixing image resolution
As you already know, this affects images negatively, since the browser scales the image as well. Your 230x230 CSS pixels picture becomes 460x460 device pixels, using the same quality. To fix that, use the srcset attribute to give the browser links to different resolution files of the same image.
Example (adapted from the link above):
<img src="wolf-400.jpg" srcset="wolf-400.jpg 400w, wolf-800.jpg 800w, wolf-1600.jpg 1600w">
An iPhone 6 will look at that and think "oh, I pretend to be 375px wide but I'm actually 750px, so I'll download wolf-800.jpg."
Just don't forget to use src="" for compatibility. Also, unless you use sizes="", the browser will default to the full width of the device.
Related
Why do we need these 3 particular image types?
If I have a button on my app with a background image say, 50 pixels x 50 pixels, why do I need 3 versions of this image? What's stopping me from just making one image that's much higher in res, say, 700x700 so when it shrinks down on any iPhone it won't fall under the max res the device would want?
Only thing I can think of is it just takes up more space, but for simple apps / a simple button it seems like it wouldn't cause any issues. I've tried it on a few devices and see no difference between them when I simulate it and do this method. However, as I dive more into apps and stuff I'm sure there is substance behind this technique.
If you don't have the exact size, there are two things that can happen:
Upscaling
#3x or #2x can be upscaled from #1x but usually the visual result is blurry, with thick lines and doesn't look good. Upscaling #3x from #2x can be even worse because subpixels must be used.
Downscaling
In general, the results are much better than with upscaling, however, that doesn't apply for all the images. If you have a 1px border on a #3x image, after downscaling it to #1x the border won't be visible (0.33px). The same applies for any small objects in the image. Downscaling destroys all details.
In general - for an image to look perfect, you want to avoid both downscaling and upscaling. You can always go with only #2x or #3x images and add other scales only if you see visual problems. Using higher resolution won't improve downscaling. High resolutions are used only to avoid upscaling. Downscaling from a high scale (e.g. #100x) to #1x won't create better results than downscaling from #3x.
You need 3 kinds of images in Image Assets because in terms of Scaling or Pixels
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 4+)
Retina iPhone6 and iPad which terms to 9 pixels (3 x 3) = 1 point#3x (iPhone6+)
Thus for providing same image in 3 scales iOS decides which image to show for which devices.Hope could help you understand this.
EDIT
It is because if you provide one high resolution graphic it would be waste of space on a users' device. Thanks to app slicing the device will download (from App Store) only the parts that actually fits the device (so retina device won't download non retina graphics). This is why Apple created assets catalogs and this kind of rules to follow. They describe it in their sessions.
In short it is to decrease memory/disk usage so it is all about increasing performance and user experience
First of all, you need to know points vs. pixels behaviour. On non-retina devices, point vs pixels ratio is 1point=1pixel. On retina devices, there are two ratios: 1point = 2x2 pixels depending on screen size, and 1point=3x3 pixels, because of pixels density, that is quadrupled watching on non retina. That's why you need this 3 types of images, to be shown on its highest resolution.
Complementing what Sulthan said:
Because you didn't propitiated proper images for a specific device, it has to downscale or upscale. These processes will use up your memory and processing, resulting maybe in a decrease of performance, depending on how many images at a time you're doing it and the size of image.
If you provide only one big image you encounter several problems:
Downscaling leads to the loss of quality (even if it is not huge)
It takes more computational power to downscale the image than to display the already pre-rendered image
The size of your binary gets increased and you are not able to benefit from app thinning which is introduced with iOS 9.
As you can see, producing only one image will impact the performance and quality of your app and it will disproportionately hit those with older devices. This is because:
They need to downscale more. Also, the performance of their devices is not as good as that of the new ones, so they are much more likely to notice the lags with your app
They do not have as much storage space so you really want to be able to use app thinning to help them
The loss of quality will be the highest for them and considering the fact that the resolution of their devices is low, they will notice it.
Due to this users are likely to be unhappy and this is bad for you. Because, from my experience, unhappy users are 10 times more likely to rate your app than happy users. You don't want that, do you? :)
The apple guides haven't helped me too much with this but I am starting to get serious about IOS development and was taken aback when I saw images go from #1x to #3x.
One source I found said they were based on sizes. For example:
If you are working on an inferred VC size and your image is 30x30 and you run that on a iPhone6 then your image should be 30x30 for #3x, 20x20 for #2x, and 10x10 for #1x.
Another source I said mentioned that it was based off the images resolution and not the size of the image.
Could someone clear this up for me and explain how to make sure my images look professional for all screens?
Thanks in advance!
When the first iPhone (and SDK) came out, all images were 1x (1 pixel of the image = 1 pixel of the screen), because that's all we had to care about. On that phone there were 166 horizontal or vertical pixels per inch (dpi). So to display an image that stretched from the left edge to the right edge, our image would need to be 320 wide (because that's what Apple told us - we didn't have to count pixels) by whatever height we wanted. Let's say 100 pixels tall. We'd name that image MyPhoto.png (because Apple told us the iPhone OS worked best with PNG images) and we'd display it.
When the iPhone 4 came out with the retina display, its retina display had 2 times the horizontal and 2 times the vertical resolution of the older phones. So now we needed higher resolution images to get the best looking interface. We were still displaying just a 2" wide image, but it would need twice the number of horizontal pixels and twice the number of vertical pixels (4 times the total number of pixels) to fill the same space. So now our image needs to be 640 pixels by 200 pixels. Since our app would still need to support the older phones as well as the new phones, we didn't want to just replace the old image with the new one. We needed a way to support both. So the old images kept the same name they had before (we didn't append "#1x") and the new images got the "#2x" filename extension to indicate they were twice the resolution. So we'd name this larger image MyPhoto#2x.png.
A common question is why not use just the higher resolution images on both old and new phones? With scaling, both appear to work great. The problem primarily is that the iPhone, especially the older phones, had very limited memory to work with. Using images that are 4 times larger than they need to be is really hard on that limited memory. That's why we had to have both 1x and 2x images in our apps.
For our sanity, we would still just use 1x while designing the interfaces. So screens remained 320 pixels wide in our code, even if we were going to display them on a retina display that was 640 pixels wide. If we wanted to draw a 1 pixel wide line on the retinal display, we'd make it half a pixel wide in our code.
With the larger screen of the iPhone 6 Plus, Apple had to pack even more pixels on the screen to maintain the high resolution customers came to expect. So now we're into 3x images. However, the iPhone 6 Plus doesn't really have three times the number of horizontal or vertical pixels. But again Apple has kept us sane by just asking us to supply "#3x" images, and it worries about scaling them down a bit on the device. As before, we still need to support smaller screen resolutions too, so we still include "#2x" and the 1x images in our apps.
So, to continue our example, the #3x image would need to be three times the width and height of the 1x image. So now we need a 960 wide by 300 pixel tall image. We'd name it MyPhoto#3x.png.
Notice that although I mentioned earlier something about a 166 dpi display, that's not really important when creating these images. In your photo editing app you don't really care if the image is 166 or 72 dpi or anything else. The only important part is the number of pixels in width and height of the final image we export.
So to answer your question (hopefully), you'll want to include all three of these images in your iPhone compatible apps. You can skip the #3x image for iPad-only apps, because there's no 3x screen yet for the iPad. But continue to think only in the 1x size when working in Interface Builder and code.
For example, now to display a 1 pixel wide line on the iPhone 6 Plus, you'd draw a 0.33 wide line rather than a 1 point line. Of course, you still want to support all of the other screen resolutions too, so you'd use code like this to set your line width:
let lineWidth = 1.0 / UIScreen.mainScreen().scale
This will give you 1.0 for the non-retinal iPhones, 0.5 for the iPhone 4, 5 & 6, and 0.33 for the iPhone 6 Plus.
is it not enough to supply just 3x resolution image (e.g for a view or button) in Xcode so that it looks good on iPhone 5,6,and 6plus devices
( i.e leaving 1x and 2x in an image set blank )
My reasoning is that 1x image may look blurry on 6 plus but 3x image should look fine on 5
Basically i am asking so that i can communicate the same to my graphic designer and he should be fine with supplying a singe size rather than three sizes for all images
This got asked and answered many times regarding 2x assets, and the answer hasn't really changed (but it's hard to track down duplicate questions when I'm posting from my phone).
If you ship assets with a higher scale factor than the target device, they will display just fine. But downscaling them in real time has performance costs—they use more memory, they take longer to upload to the GPU, they take GPU time to render. Some of these costs are trivial, others aren't. (Remember, a 2x image is 4x the data of a 1x one, and a 3x image is 2.25x the data of a 2x one.) And they add up for every image in your app.
Most importantly, the devices with lower scale factors are the ones with less CPU/GPU/memory resources to spend on downscaling.
So, what to do? Well, if you don't want to have your artist deal with multiple scale factors, just order the 3x artwork and scale it yourself in Photoshop (or heck, even Preview) before you ship. It might not look as nice as if your artist tweaked it for each size, but it'll look about as good as real-time scaling without the run-time performance costs.
Or, with Xcode 6, you can put a PDF in your asset catalog, and Xcode will automatically generate PNGs for each size at build time. (This is an Xcode feature, not an iOS one, so it works even if you're targeting iOS 7.)
The problem with this idea is that in iOS 8 the iphone 4S is still supported and it has a different aspect ratio than every other iPhone. It renders at 320x480 at 2x so creating images to fit this wouldn't look grainy. The other 3 screen sizes would work if you go with the 3x scale which would be 1920x1080 for every page and just downscale the size for the 4in and 4.7in screens. You will likely need 2 story boards for the app (one for 3.5in and then the other for the 3 other screen sizes). Auto-sizing wouldn't really work in this case unless you changed the image of the UIImage because it would have a shortened length while maintaining the same width.
EDIT: changed the iPhone 6+ screen size to account for the 1.15x down scaling
and changed the rendering factor to match the comment below
I am using JQM with HTML5 boiler plate. My objective (for tests purposes) is to have in a desktop browser, an overall div that will show me the expected size areas of my app on a real device. In a desktop browser, however, the width compared to the iphone4 browser width layout do not seems to match. I do not wish to change the viewport meta definition, although I suspect that it is my problem. Can somebody explain to me:
Why the size of a div of size 640 x 960 px (with a border of 1 px and a position of absolute) does not reflect the same size area appearance on the actual device with this type of setup ?
Regards.
Just use Chrome's Developer Tools. You can choose to spoof your User Agent as well as the device metrics for different devices.
When in Chrome:
Press F12.
Click on the gear icon to the bottom right (settings).
Click on the Overrides tab.
Here you can choose to change your User Agent string or override the viewport of your browser to match specific devices (like the iPhone). If you change the User Agent string to mimic an iPhone then the Device Metrics should auto adjust to be the proper size for the same device.
Note that you must keep the Chrome Developer Tools open, as soon as you close them you lose the UA spoofing and Device Metrics spoofing as well.
To directly answer your question, different screens have different pixel densities, so a screen with higher pixel density will show the same number of pixels in a smaller physical area.
As an add-on,
When dealing with CSS Media queries there is a difference between the
device-width and the
width.
For the iphone4, for instance, although the resolution
(width x height) is equal to (640 x 960),
the device is actually presenting
(device-width x device-height) as equal to (320 x 480)
From here we observe that each CSS pixel is handled by 2 screen resolution pixel. This is the consequence of the 2 different size.
This help: Pixel density for different devices
I designed my first ipad app.
And when i run it on the simulator resolution is really small. Smaller than really ipad's resolution. Right now i have not ipad, and cant test app on it.
What the problem with resolution?
UPD I connect big display to my macbook. But resolution is still small. I think thats because macbook's display is primary and big monitor is the second. How can i change it?
The problem is that the physical resolution of your screen is lower than the physical resolution of the iPad’s screen. For example my iMac’s screen has 1920 pixels per ~19 inches of width, or roughly 100 pixels per inch. The iPad’s screen density is about 130 ppi, one third higher. If you’re serious about your app, you have to test on the real device anyway. (By the way, if you are simply talking about the window size, that can be changed in the Window menu or using ⌘1–⌘3 shortcuts.)