If you are a programmer creating web sites you are aware that your web site is going to be visible on multiple devices, screens and browsers. This is serious problem because if your web site is not visible for some users, these are probable clients that you have lost. The biggest problem is that there are thousands of devices out there and they all use different screen sizes and resolutions. Normally you didn’t write design for every one device and test against it but you use different techniques media queries, separate mobile sites, etc. This is all great to allow the site to have good layout on different devices, but the things
become different when you use different design with the same content images. For example for PC with 22 inch monitor Full HD your site may show a beautiful landscape Image with lot of details buildings and trees but on 4 inch display you will probably not recognize any details on the picture and the whole idea may be lost, also there is the problem of downloading this big picture over cellular network if you don’t need it. This is known as the responsive images problem. There is a whole group devoted to resolving this problem known as the Responsive Images Community Group.
There are several proposed ways to resolve the issue for more information on the problem you can checkout this links:
I will try to resolve the problem in ASP.NET using
HttpHandler to process the requests for image and deliver the desired image to
the client, based on client device resolution and other parameters. This approach
is similar to the one used by
http://adaptive-images.com/.
Solution
Client
We will use javascript to collect the information about the
device and set it to the cookie of the domain that deliver the images. Some
sites use different domain for images than the one for the main site to boost
efficiency.
First we check if the browser enabled cookies. If this is not the case the javascript will not execute at all and the server is supposed to deliver the default image, solutions like sencha.io use the information from “User-Agent” to deliver different images for different devices but this do not cover the different resolutions for PC and as the count of the devices grow we will have to support constantly increasing base to keep up. Also some solutions that use javascript to build dom element on the fly and embed the information in the url, but I think this is additional work for the browser and also the browsers start the loading of images before the dom is fully loaded to save time and most DOM manipulations need to be done after DOM loaded.
We setup the cookies with names RIWidth, RIHeight based on the screen width and height, also if the navigator.battery information is available we set it to “RIBattery”
Also we use the navigator.netInfo or the navigator.connection if exists to determine the internet connection speed of the device and send information of it, so if the device has slow internet connection not to send the biggest available images. The information and conditions here can be much more complex based on the “The Network Information API”, but for now we will just use simple bandwidth property for minor check.
Request should include cookie information like: Cookie: RIWidth=1920; RIHeight=1080.
.NET Server
On the server we will use
IHTTPHandler to deliver the images. For the purpose we create one named
ImageContentHandler and include it in the web.config.
We also create
XML with the screen resolution we will support. We will create and deliver
images that will be perfect for this resolution screens and will be slightly
off for different resolutions.
The default attribute indicate if no information is passed
to the handler witch is the default image size to return.
When a request come for a given image we first determine the
screen resolution image to return based on the passed cookie information, if
the battery is below 15% or the network speed is below 600KB/s we will deliver
maximum of 800x800 resolution else if the network speed is below 1.5MB/s we
will use max 1500x1500 resolution. Based
on the maximum available resolution and the device/browser dimension we choose
the desired resolution format, for example if the device resolution is
1920x1200 or 1800x900 we will use 1080p, but if the network speed is 500KB/s we
will return image for resolution WGA. You
can play with these properties to create different scenarios.
When the desired resolution is chosen we check if image
for this resolution exists in the Images folder. So if we must return image for
1080p resolution we check if such image exists in the “Images/1080p” folder and
return it.
If the image for the desired resolution do not exists in
images we try to get one from the “Images/Cache/XXX” directory. This is the
directory in which we will create images that do not exist in the main images
directory. So if we do not find any image there we find the next resolution in
which this image exists and resize it to the desired resolution.
For example if we need image “logo.jpg” for “WQVGA”
resolution device but we have image named “logo.jpg” in “Images/WGA” with
dimensions 200x100px. We will try to return the image first from “Images/WQVGA/logo.jpg”
and “Images/Cache/WQVGA/logo.jpg”, but initially the both images will not
exists and after that we will resize the image “Images/WGA/logo.jpg” to
resolution 100x50 and save it to “Images/Cache/WQVGA/logo.jpg” and return that
image. The next time the same request comes we will return the already resized
image. This newly resized image will have smaller size than the one for the
bigger resolution and the time it take to resize the image should be smaller
than the time the device need to download the bigger picture over slow cellular
network, especially if we have image in the 4K resolution.
The final step is for our ImageHandler to use ETags to
return the images. The basic idea is after the first time ImageHandler return
an image the browser receive ETag unique string. The next time the browser send
request, the ETag is included and if the image is not changed on the server the
ImageHandler do not return the image but a 304 Not Modify response.
The LookupEtagFromInput
method return unique string for the file. Currently we get the file content
converted to MD5 hash, but different methods can be used for faster ETag
generation like converting name and modify date to base64.
Code Reference: https://github.com/rosenkolev/ASP.NET-Responsive-Images