What does -webkit-min-device-pixel-ratio: 2 stand for? - iphone

#media only screen and (max-device-width:480px),
only screen and (-webkit-min-device-pixel-ratio: 2)
{ /*iphone css*/ }
max-device width makes sense but pixel ratio doesn't make any sense to me. thanks.

From http://developer.android.com/reference/android/webkit/WebView.html
The -webkit-device-pixel-ratio CSS media query. Use this to specify
the screen densities for which this style sheet is to be used. The
corresponding value should be either "0.75", "1", or "1.5", to
indicate that the styles are for devices with low density, medium
density, or high density screens, respectively. For example: The hdpi.css stylesheet is only used for devices
with a screen pixel ration of 1.5, which is the high density pixel
ratio.
And according to https://developer.mozilla.org/en/CSS/Media_queries
-moz-device-pixel-ratio
Gives the number of device pixels per CSS pixel.
Note: This media feature is also implemented by Webkit as
-webkit-device-pixel-ratio. The min and max prefixes as implemented by Gecko are named min--moz-device-pixel-ratio and
max--moz-device-pixel-ratio; but the same prefixes as implemented by
Webkit are named -webkit-min-device-pixel-ratio and
-webkit-max-device-pixel-ratio.

Related

Is there a way to define a view's frame in terms of inches instead of points?

Given any screen resolution, is there a way that I can figure out the amount of points in an inch? For instance, if I wanted to create an NSView that was 8.5 inches by 11 inches (like a sheet of a paper), is there an algorithm that will allow me to obtain the correct point values for the frame across many different types of Macs and screen resolutions?
It's not straightforward. I'm not sure there's a good way. I can provide an approach, but I haven't confirmed that this works reliably:
First, you can use CGDisplayScreenSize() to get the screen's physical size in millimeters. You can obtain the CGDirectDisplayID for a screen from NSScreen, which you can, in turn, get from the window. Obtain the screen's deviceDescription and get the value for the "NSScreenNumber" key. That may need to be cast to CGDirectDisplayID.
The problem from there is that the display mode may not fill the screen. It could be letterboxed or pillarboxed. Or, it might be stretched. This should be fairly uncommon these days, but still possible. You can obtain the display mode using CGDisplayCopyDisplayMode(). To determine if it's stretched, you can examine its ioFlags to see if they contain the bitmask kDisplayModeStretchedFlag (declared in IOKit).
If it's stretched, the screen's frame will have to be mapped to its size in millimeters separately for the X and Y axes. You assume the screen's frame.width (in points) maps to the full physical width, and similarly for the height.
If the mode is not stretched, you'll have to check the aspect ratio of the frame and the screen physical size to see if it's letter- or pillarboxed. If the aspect ratios are very close, then it's presumably not. That case is similar to the stretched case, but the width and height mappings should be equivalent.
If the aspect ratios differ significantly, then you compare them. If the screen's physical aspect ratio is larger than the frame's, then the screen is physically wider than the mode is using (pillarboxed). So, you compute the mapping from points to millimeters from the two heights. If the physical aspect ratio is smaller than the logical one, then the mode is letterboxed and you use the widths to compute the mapping.

Images being upscaled in Flutter

I have images stored as blobs in SQLite. Other tools like DB Browser for SQLite show the images themselves are not upscaled.
I scaled them down from an original image with the following code.
final thumbnailData = encodeJpg(copyResize(
decodeImage(imageData),
width: 400,
interpolation: Interpolation.average
));
When displayed in Flutter they are noticably upscaled.
#override
Widget build(BuildContext context) {
return Image.memory(_getThumbnailData());
}
Image.memory() has a scale argument that defaults to 1.0. Setting it manually to be sure doesn't help either.
I have to set it to some guesstimated value like 2.0 to get the correct scale but I don't understand why and wether 2.0 is actually "unscaled" or still slightly off.
How can I tell Flutter to display the images as they are?
Flutter uses logical pixel instead of physical pixels.
Device pixels are also referred to as physical pixels. Logical pixels are also referred to as device-independent or resolution-independent pixels.
How to convert between physical pixels and logical pixels?
To convert between physical pixels and logical pixels, you can use devicePixelRatio.
The number of device pixels for each logical pixel. This number might not be a power of two. Indeed, it might not even be an integer. For example, the Nexus 6 has a device pixel ratio of 3.5.
MediaQuery.of(context).devicePixelRatio

Responsive image resolution iPhone vs iPad

I want to use srcset to provide 2x images for iPhone and iPad, but the 2x descriptor applies to both and the images should be different.
On both devices the image is full width. But on iPhone 2x of 320w is 640w and on iPad Pro 2x of 1024 is 2048w.
How could I differentiate between the two?
The x descriptor is more suited to images which width is fixed across viewports.
For variable width images, you should use the w descriptor.
For example:
<img
src="image320.jpg"
srcset="image320.jpg 320w, image640.jpg 640w, image960.jpg 960vw, image1280.jpg 1280vw, image1600.jpg 1600vw, image1920.jpg 1920vw, image2240.jpg 2240vw, image2560.jpg 2560vw"
sizes="100vw">
The w descriptor applies the screen density factor to the CSS width of the image to get the actual image width to download.
The image1920.jpg image will be downloaded by the browser for several configurations:
screen density 1 with viewport width equal to or below 1920px
screen density 2 with viewport width equal to or below 960px
screen density 3 with viewport width equal to or below 640px
etc.

Autolayout Contraints for a View from XIB

I am loading a view (shaped a circle) from a circle. I want to make sure, the circle's size adapts to various screen sizes. So far I tried placing the view inside another view, pinning the margins to the superview and then setting the superview's aspect ratio to 1:1. This gives me a circle. However, now, I want to change its size. Currently, the superview's size is specified by another subview in it, a label. Depending on the contents of the label, the superview's size changes (I have set the label's font size to Autoshrink). If I try to add a constant to the margin constraints it works, but looks the same size across different screen sizes. Also, I tried adding a multiplier, while the multiplier works for trailing and bottom margins, top and leading margins don't get affected by setting the multiplier. Below is a screenshot of the IB (Today View is the shape in the question).
You have a good start - aligning both center X & Y, 1:1 ratio. All you need to add is two sets of top/bottom and leading/trailing constraints with different priorities. Here's an example, which combined with the three constraints you have, would center a view in all orientations with a 10 point border along the narrower axis:
Priority == 750
Top == 10 points
Bottom == 10 Points
Leading == 10 points
Trailing == 10 points
Priority == 1000
Top >= 10 points
Bottom >= 10 Points
Leading >= 10 points
Trailing >= 10 points
You may see errors/warnings while doing this because IB doesn't know how to render it, but once you've completed this, you'll have what you need.
EDIT:
From memory, there are points and pixels. When and where possible, try to think in terms of points. About the only time you may wish to think in terms of pixels is with images. (There may be other measurements of graphics, but again, I'm writing from memory.)
Points should be consistent across device size - so if you have a 100x100 square in a 4 inch iPhone screen, it will be the same size on a 12.9 inch iPad Pro.
More importantly, the margins can be set the same using auto layout. A 25 point margin will be the same on both of those screen. So in my example above, you will get pretty much the largest rectangle possible across all devices since you are setting margins, not view size.
I did a dive into screen sizes last year, and these are the current screen sizes:
//iPad Pro 1366x1024
//iPad 1024x768
//iPad Mini 1024x468
//iPhone 6 Plus 736x414
//iPhone 6 677x375
//iPhone 5 568x320
//iPhone 4 480x320
So based on this the above constraints would yield a 300x300 square on an iPhone 4 (iPhone SE also) as the narrowest axis will be 320 less two 10 point margins. And on an iPad Pro 12.9 inch it will be a 1004x1004 square.
When you create constraints in code, you can also create a layoutMarginGuide with this code:
let margins = view.layoutMarginsGuide
This should be the same thing as keeping the "contain to margins" checkbox checked in IB. Essentially this is the recommended size of margins for each device. (I believe this should also include the status bar, tab and navigation bars, and even the iPhone "phone call top banner (sic)". But I've had some issues with this so YMMV.)
EDIT 2:
Putting this all together, what you are defining through "auto layout" is a very fluid way of maximizing the size of a square (or in your case, a square turned into a circle). By setting two sets of margins, one set equal to but with a high priority, you are letting auto layout know that it may break this over required constraints. The second set with greater than or equal to values is required.
Thus, in a 480x320 device, the top/bottom margin constraints that cannot be met ("equal to") can be broken, and in landscape the leading/trailing ones that cannot be met will be broken. Remember, you already set the center X/Y, so the view will be centered, and you set the 1:1 ratio so it will be square. (As long as you did not touch the priorities - the default is required.

CSS pixels vs device pixels on iPhone

If I specify the width of a <div> tag using CSS as 96px, how many device pixels should that occupy on the screen of a first generation iPhone?
I added <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/> to the page, took a screenshot on the simulator, and measured the div to be 96 device pixels wide. Now, I read the W3 spec for CSS pixels and it states that 1px is 1/96th of an inch. So 96 CSS pixels should translate to 1 inch. Since the original iPhone has a DPI of 163, one inch on the screen should occupy 163 device pixels. Why am I not getting that measurement? In other words, should 96 CSS pixels be equal to 1 inch?
I saw that the spec also mentions anchoring to a reference pixel. It seems to me that the reference pixel is simply a device pixel in this case. If I was to work backwards to get the CSS pixel values from a screenshot, would it generally be correct to assume that one device pixel equals one CSS pixel on the iPhone (non-retina display)?
Iphone pixels are like any other pixel. A 96px wide <div> is always 96px wide in any device. DPI (Dots Per Inch) just tell you the ratio between physical pixels (dots) on a screen (or paper) and inches and don't represent any size. DPI are only a ratio between pixels and a real world unit of measurement.
A 96px div would look 6x bigger in a 50 DPI screen than a 300 DPI screen.
DPI vary depending on the device or print/scan quality, therefore 1 inch is NOT always equal to 96 pixels. W3C is just saying that the absolute length units are fixed in relation to each other (it is just an arbitrary approximation to make CSS units consistent). This does not mean that real world units of measurement (inches, cm) can be given a fixed ratio to pixels.
The best help i can give you to understand this is that 1px is only and always equal to 1px. Any comparison between pixels and real world units depends on the DPI of a specific device, not on a standard like the W3C.
The absolute length units are fixed in relation to each other and
anchored to some physical measurement. They are mainly useful when the
output environment is known.