{"id":76241,"date":"2017-12-14T15:20:51","date_gmt":"2017-12-14T15:20:51","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=76241"},"modified":"2021-05-11T15:56:10","modified_gmt":"2021-05-11T15:56:10","slug":"adapting-images-websites","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/dotnet-development\/adapting-images-websites\/","title":{"rendered":"Adapting Images to Websites"},"content":{"rendered":"<p>Websites would not be the same without images or, better yet, without crisp and clear images. Albeit necessary, images are often the primary source of trouble for site visitors. If a page is slow to load and is perceived as \u2018bloated\u2019, then 99% of the time it\u2019s because of large and heavy images. There are many ways to reduce the impact of large and heavy images on web pages. In this article, I\u2019ll explore and describe a couple of approaches, ranging from simple offline manipulation and downsizing of images to server-side resampling through ad hoc frameworks. The latter approach is particularly suited when you need to optimize the use of images in mobile-friendly websites.<\/p>\n<p>A few days ago, I logged into my PayPal account after a very long absence. I had no memories of the site home page and noticed that it currently looks like the image shown below. As you can see, the PayPal home page features a full-page, colorful image of very good quality. I had to assume that the image was also fairly large in terms of size. Yet the page was very quick to load.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1148\" height=\"719\" class=\"wp-image-76242\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2017\/12\/word-image.png\" \/><\/p>\n<p>That immediately brought to mind an experience I had years ago with the home page of a website I was working on. The layout of that home page was very close to the PayPal home page in the figure, and, to achieve an astonishing effect, I initially used a high-quality image, 3264&#215;1824 in dimensions. The actual weight of the image was in the order of 2 MB. As you might expect, it worked acceptably well on desktop browsers, but it was decidedly too slow for other devices. However, even on desktop browsers it never felt quick. Images are nice to have, but they are even better if the user just sees them immediately. A pleasant and appropriate image reaches its communication goals especially if the user perceives it as just-being-there, like plain text. I know that someone else took care of fixing the large image I had on the home page, and the site went live without issues. I didn\u2019t ever manage, though, to find out what the UI guys did to make the home page enjoyable. Even if you are a developer, no excuses: here are some tips to keep background images high quality but still quick to load.<\/p>\n<h2>Offline Downsizing of Images<\/h2>\n<p>The first tip is to reduce the quality of the image through a technique known as downsampling. The dimensions of the image remain the same, but the number of pixels stored in the image is reduced. Subsequently, the size of the image file diminishes significantly. Downsampling is the core technique behind functions like <em>Save for Web<\/em> that you find in many image processing products and primarily in Adobe Photoshop. A JPEG image, for example, is obtained through a lossy form of compression from the matrix of pixels originally captured by the lenses of the camera. Downsampling just reworks the color of stored pixels giving some of them the same color of their neighbor pixels. To exemplify, let\u2019s consider a photo I took this summer on vacation with my smartphone.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1471\" height=\"822\" class=\"wp-image-76243\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2017\/12\/word-image.jpeg\" \/><\/p>\n<p>The dimensions of the original image are 3264&#215;1824 pixels and the size of the file is about 1.4 MB. This is too much for an image to be used on a website open to any device. (You can find the original unmodified image <a href=\"https:\/\/3jggxa.by3302.livefilestore.com\/y4mzde1DD9vWaxUjW6NGRi61Vb307H64fR8Y5ov_RcQU0HGUKSTKuc18WA3TJiNINDhLijxF7WIHWU0zRPcbmwN03rPYAt21CE0M4kF4M4iKMrJqyKrrPHL4ygAr-N-nT1qfDtYAJoNgtB0CnZ7d-brACS7w9RJ1eo50AW23_qfVmhEPa_ByuV2YZ0v2DYEYP421mvkKDOW5NvqASLl5F1caA\">here<\/a> if you wish to follow along.) I then uploaded the original file to <a href=\"http:\/\/optimizilla.com\">http:\/\/optimizilla.com<\/a> and had it downsampled. (Except for the configuration of the algorithms, it is the same as using the <em>Save for Web<\/em> function of Photoshop.)\u00a0<\/p>\n<p>The <a href=\"https:\/\/ax8jda.by3302.livefilestore.com\/y4m-1-Z5rlVkttDH8v7LFeTQGp0Sn_0hIJ3NbEbS7SLE2zywe6uJ87mU11jYyb0S-1qDXQ4DK-mQFjqwVH59l61krZtTEoSFYP_vgF4tvPb1LaRE1xPkZQDWhcSuOzdJjUUAA54sHRCWiEf7xeRanLdKG9s-VYNl0XM0OVK92GTt47fkg32pW6mO6j4glBih8sBFHoWQxrrhDKsGifta_s27g\">image<\/a> I received back had the same dimensions as the original image, and the human eye won&#8217;t likely notice any difference or, at least, no differences that are relevant for the use case. The size of the second image file, though, is about one third of the original.<\/p>\n<p>At this point, you can proceed with a classic resizing step. A 3000&#215;2000 image is definitely too large for the vast majority of web scenarios. A width of 1600 pixel is considered sufficient today for most cases and, not coincidentally, that\u2019s exactly the width of the PayPal home image I referred to earlier. The height of the image, instead, depends on the layout of the page. A height somewhere in between 500 and 1000 pixels is reasonable. (PayPal\u2019s image is 1600&#215;600.) Resizing the sample image to 1600 pixels wide leads to a file size of 257 KB. If you take a look a the <a href=\"https:\/\/0kp7aq.by3302.livefilestore.com\/y4mGaFKD4EXjH6dyN9N2RtGII0XpNARgxbFA6xgb2raELJin0Cbxvl-pZo4MMxb_3OojX1a0XaitP2SnGvZS95LKQj8vOeT3QfZOFZ3vpFtAnhgzl7UOQanzDsp-OGiQr5XqvzZPf-9nsgWNRSXLCLVUAoiSQoKlSWsOSk2L1_98dlUAz2Nsb0Jt6CjFS0Q4yxvfWTvDjGXCRX_iRD7uNcn4w\">final image<\/a>, you will see that it looks identical to the original despite the much smaller file size.<\/p>\n<p>In the end, I started with a 1.4 MB image and ended up, through a couple of simple offline steps, to a 257 KB image that looks nearly the same and, more importantly, loads instantly. By the way, the size of the PayPal home page image is 370 KB.<\/p>\n<h2>Optimizing Images for Smaller Devices<\/h2>\n<p>Sometimes you just don\u2019t want, or can&#8217;t afford, to have a single version of the image serving all possible devices visiting your site. For a good service, the image size should be appropriate for the computing power of the device, to say nothing of the network. Because of the different screen sizes of smaller devices (e.g., smartphones versus large HD screens), sometimes the image must be cropped and not just resized. Cropping is a delicate art as it involves removing details yet must leave the meaning and the context of the image intact. In other words, when it comes to devices, serving an appropriate image is both a matter of quantity (of bytes) and quality (art direction). How can you specify multiple versions of the same \u2018logical\u2019 image?<\/p>\n<p>At the moment, there are two main approaches to serving the most appropriate version of an image to each requesting device. The official solution, being pursued by the W3C, is using a new HTML element\u2014the <strong>PICTURE<\/strong> element. You can think of the <strong>PICTURE<\/strong> element as a superset of the <strong>IMG<\/strong> element. The element doesn\u2019t directly cause any rendering, but it instructs the browser on which image to select based on detected conditions. At present, conditions you can express within the <strong>PICTURE<\/strong> element are media query expressions. Media queries are expected to improve the range of conditions they can check, but currently media queries can&#8217;t really tell whether the device is a true mobile device or a desktop browser resized to a small window. The second approach is to serve the most appropriate version of an image to a requesting device through a server-side endpoint that automatically resizes or crops the image before serving it. Let\u2019s find out more about the two approaches.<\/p>\n<h2>The PICTURE Element<\/h2>\n<p>The purpose of the <strong>PICTURE<\/strong> element is to avoid the automatic browser scaling of images. The <strong>IMG<\/strong> element\u2014the old familiar way of displaying images in HTML\u2014points to a given image and the image is downloaded as-is. It\u2019s then resized on the client, for display purposes, to the dimensions set via CSS. The <strong>IMG<\/strong> element can be bound to a single endpoint that returns an image stream.<\/p>\n<p>The first issue with this approach is that you need a single image that fits all possible requesting devices. Unless the website (or a specific page) is primarily designed for mobile devices, the size of the image has to be the largest that could possibly be a good compromise between quality and speed. If you\u2019re going to use a single image, then all tips outlined above on how to gracefully reduce quality and size should be applied. When a large image is shrunken down to fit in a small viewport, though, the resulting picture might not be easy to see. Imagine a large picture with a relatively static and flat background (e.g., meadows, a blue sky, ocean) and a small detail such as a sailing boat or a flower. When reduced to a small size, the small detail can become incredibly small. This is because a blind resize (without cropping) uniformly cuts rows of pixels throughout the image matrix.<\/p>\n<p>The <strong>PICTURE<\/strong> element, instead, allows you to link multiple images each associated to a given media query expression. The browser will then intelligently select the first image that fits. Here&#8217;s the syntax.<\/p>\n<pre class=\"theme:vs2012 lang:xhtml decode:true\">&lt;picture&gt;\r\n    &lt;source media=\"(min-width: 541px)\" srcset=\"~\/content\/images\/ocean_md.jpg\" \r\n            class=\"img-responsive\"&gt;\r\n    &lt;source media=\"(max-width: 360px)\" srcset=\"~\/content\/images\/ocean_xs.jpg\" \r\n            class=\"img-responsive\"&gt;\r\n    &lt;source media=\"(max-width: 540px)\" srcset=\"~\/content\/images\/ocean_sm.jpg\" \r\n            class=\"img-responsive\"&gt;\r\n    &lt;img src=\"~\/content\/images\/ocean.jpg\" class=\"img-responsive\"&gt;\r\n&lt;\/picture&gt;\r\n<\/pre>\n<p>You use the <strong>media<\/strong> attribute to set the breakpoint where the browser must switch the image. If the viewport is within 360 pixels, then the <strong>ocean_xs<\/strong> picture is served. If it\u2019s between 361 and 540 pixels, the browser will serve <strong>ocean_sm<\/strong>. Finally, for larger screens, the browser will serve <strong>ocean_md<\/strong>. If the browser doesn\u2019t support the <strong>PICTURE<\/strong> element, the embedded <strong>IMG<\/strong> element will be processed.<\/p>\n<h2>Resizing Images Dynamically<\/h2>\n<p>An alternative to using the <strong>PICTURE<\/strong> element is having images automatically resized on the server before use. You can arrange your own infrastructure or use a commercially available imaging resizing service. The primary purpose of an image resizing service is operating as a smart Content Delivery Network (CDN) and acting to reduce the image payload of pages and subsequently the load time. Such a smart CDN is particularly useful to improve the service on mobile devices.<\/p>\n<p>As an example, let\u2019s consider <a href=\"http:\/\/wurfl.io\">ImageEngine<\/a>. ImageEngine is a web service that provides device-specific resized images. ImageEngine doesn\u2019t just save valuable time and bandwidth while downloading images, but it also saves you from the burden of maintaining multiple versions of the same image tailor-made for various screen sizes. To get started, request a test account that you can use for 30 days. You will be given a token to add to your image URL which runs the image through the service. Let\u2019s say you need to display the following images from within a web page.<\/p>\n<pre class=\"theme:vs2012 lang:xhtml decode:true\">&lt;img src=\"\/images\/ocean.jpg\"&gt;<\/pre>\n<p>The image can\u2019t be referenced through a relative URL, so its fully qualified name is passed as an argument to the ImageEngine endpoint. When using ImageEngine, instead of the original code you use the following:<\/p>\n<pre class=\"theme:vs2012 lang:xhtml decode:true\">&lt;img src=\"\/\/{account}.imgeng.in\/http:\/\/contoso.com\/images\/ocean.jpg\"&gt;<\/pre>\n<p>If your account is contoso, then the <strong>IMG<\/strong> element will be:<\/p>\n<pre class=\"theme:vs2012 lang:xhtml decode:true\">&lt;img src=\"\/\/contoso.imgeng.in\/http:\/\/contoso.com\/images\/ocean.jpg\"&gt;<\/pre>\n<p>The ImageEngine framework silently downloads and caches the original image. When the image is requested, ImageEngine can do some handling before returning it to the device. For example, ImageEngine has the ability to resize the image appropriately but also to crop it. By default, the framework scales down the image to the size it reckons ideal for the device. This is only the default behavior though. You can specify additional parameters, called Directives, to request some ad hoc behavior. The table below lists the options available.<\/p>\n<table>\n<thead>\n<tr>\n<td>\n<p>Parameter<\/p>\n<\/td>\n<td>\n<p>Description<\/p>\n<\/td>\n<td>\n<p>Sample URL<\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\n<p>w_NNN<\/p>\n<\/td>\n<td>\n<p>Desired width of the image<\/p>\n<\/td>\n<td>\n<p>\/\/contoso.imgeng.in\/w_200\/IMAGE_URL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>h_NNN<\/p>\n<\/td>\n<td>\n<p>Desired height of the image<\/p>\n<\/td>\n<td>\n<p>\/\/contoso.imgeng.in\/h_200\/IMAGE_URL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>pc_NN<\/p>\n<\/td>\n<td>\n<p>Percentage of reduction<\/p>\n<\/td>\n<td>\n<p>\/\/contoso.imgeng.in\/pc_50\/IMAGE_URL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>m_XXX<\/p>\n<\/td>\n<td>\n<p>Resize mode. Accepted values: box, cropbox, letterbox, stretch<\/p>\n<\/td>\n<td>\n<p>\/\/contoso.imgeng.in\/ m_cropbox\/w_200\/h_200\/IMAGE_URL<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>f_XXX<\/p>\n<\/td>\n<td>\n<p>Output format. Accepted values: png, jpg, webp, gif, bmp, jp2, jpegxr.<\/p>\n<\/td>\n<td>\n<p>\/\/contoso.imgeng.in\/f_png\/IMAGE_URL<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Multiple parameters can be combined together as different segments of the URL. The order of parameters is unimportant.<\/p>\n<h2>Comparing the Options<\/h2>\n<p>The <strong>PICTURE<\/strong> element is gaining a lot of traction and is widely supported by browsers (at least in their newest versions) with the only significant exception of Internet Explorer, Opera Mini and old Android browsers. Its main drawback is that site administrators must maintaining multiple copies of the same image, one for each screen size (or media query) supported. It is effective but, for a site with many images and frequent updates, it can be a real pain.<\/p>\n<p>Compared to the <strong>PICTURE<\/strong> element, a framework like ImageEngine is preferable because it doesn\u2019t force site administrators to deal with different images, properly resized. At the same time, a framework like ImageEngine doesn\u2019t easily support art direction. The image is automatically resized or cropped but only through hard-coded algorithms\u2014no human eye control.<\/p>\n<p>In a nutshell, none of the two solutions is free of issues, but each can mitigate the problem of serving optimized images effectively. In my opinion, the ideal solution is a further enhanced <strong>PICTURE<\/strong> element where the media attribute can recognize truly mobile devices. The ability to detect mobile devices is not currently backed in media queries but it may arrive in the future, although a future that is farther away than <a href=\"http:\/\/www.w3.org\/TR\/mediaqueries-4\/\">CSS Media Queries 4<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Creating web pages with images that look good on all devices and screen sizes is not an easy task. Dino Esposito describes how to manually prepare images and explains the currently available technology for automatic resizing.&hellip;<\/p>\n","protected":false},"author":221911,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538],"tags":[],"coauthors":[6780],"class_list":["post-76241","post","type-post","status-publish","format-standard","hentry","category-dotnet-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/76241","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/221911"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=76241"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/76241\/revisions"}],"predecessor-version":[{"id":76288,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/76241\/revisions\/76288"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=76241"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=76241"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=76241"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=76241"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}