Proposed implementation on Android: If the screen is less than 480px wide, stretch the image to 100% width. If the screen is greater than 480px, stretch the image to 400px.
Potential issues: blurry images when small thumbnails are stretched much larger, images that are meant to be larger than 400px (charts, diagrams, panoramas) being forced to be smaller on large tablet screens.
Feel free to expand the list of prerendered sizes is needed, however bear in mind the extra storage costs it entails while we still use Swift. In the case of Media Viewer that list is based on exactly the sizes that Media Viewer requests on demand. The rationale was that it's only a matter of time before all these sizes are rendered on demand and take space in Swift anyway, so might as well request them from the get go.
How would this be implemented?
Since HTTP requests do not include any information about screen resolution, it is quite difficult to properly optimize image sizing on the server-side for displaying at 100% width on arbitrary devices. You could theoretically optimize for specific user agents that you could guess the resolution for. This solution, however, entails a large amount of overhead and maintenance since you have to maintain resolution look-up tables for every device that you want to support. It also doesn't let you account for landscape vs. portrait mode, so you would only deliver the right image size about half the time. For these reasons, I think it is only practical to implement a solution for this on the client-side.
The client-side solution would be to rewrite all the image tags on page load based on the initial screen width. If the screen were smaller than a certain threshold (768px is the current phone/tablet threshold in MF, although the Android team has proposed using 480px in their implementation), the width style attribute would be set to 100%, the src would be set to a pixel value close to the 100% size, and the scrset attribute would be set to values that are 1.5x and 2x the src size. We would likely want to round the src size to values listed in $wgUploadThumbnailRenderMap if possible (or half those values for retina displays) in order to minimize new thumbnail generation.
For screens larger than the threshold, we would rewrite the image width style to a hard-coded value (like 320px or 400px) unless the image was already that size or larger, set the src to the same value, and set the srcset with the proper multiples.
We may want to consider abandoning the mobile Media Viewer if we implement this, as it won't provide much of a difference from the default view. (The main purpose of the Media Viewer is to allow viewing images at full screen width.)
Performance implications of whatever strategy we implement
There are 2 ways in which this could negatively impact performance. First, it would require generating new thumbnails every time a new size for a particular image is requested. Currently the scaling server is pre-generating thumbnails of the following sizes for all new uploads: 320, 640, 800, 1024, 1280, 1920, 2560, 2880. We could round the thumbnail request size to one of these sizes to minimize new requests. Unfortunately, the thumbnail pre-generation script has only been running since March, so it only covers a tiny percentage of the images on Commons. Thus it's not actually going to help us a lot in the short-term.
Secondly, the diversity of size requests (8 instead of 1) for each image, means that cache misses will be increased 8-fold. According to Gilles, cache misses actually have more of a negative effect on performance than new thumbnail generation, although I don't have specific numbers from him on how much of an effect it is.
Are thumbnails pre-generated or not?
Yes, see above.
Bandwidth implications (how do we know what the threshold is?)
Setting all images to 100% width (or close to it) will significantly increase bandwidth usage per page, especially on retina displays. If we look at thumbnails for a square image like File:CH_cow_2_cropped.jpg, it should give us an idea of average bandwidth implications (images with a vertical orientation will be more affected and images with a horizontal orientation will be less affected). For that image in particular, a 220px thumbnail (default size) is 25 KB, 440px (default retina) is 66 KB, 400px (new default) is 57 KB, and 800px (new default retina) is 188 KB. That represents a 2.3-fold file size increase on non-retina devices and a 2.8-fold file size increase on retina devices per image. If we adopt a threshold of 768px (as suggested by the mock-ups), the potential for bandwidth increase is much greater: up to 7.5-fold for regular displays and 9.6-fold on retina displays. In other words, each image could be up to 10 times larger than it would be otherwise (at default size with a 768px retina screen).
@kaldari thanks for this, Ryan! do you know why/how apps might have gotten away with this without such a large increase? Seems like you're saying square photos are gong to at least double in size if we do this, with vertically images having a greater increase and horizontal images having less. This seems like a lot. Obviously doubling image size doesn't double pageload time...can we guestimate the impact on pageload?