Cloudinary Blog

JPEG-XR conversion with auto browser detection, optimize images for IE users

JPEG-XR converter with auto browser detection

Sites and apps are including more and more high-quality images. The more you can compress images to reduce their size in bytes, the smaller your bandwidth, the faster your site will load and the happier your users will be. But when compressing images, you need to make sure you maintain high visual quality.

Most web sites and mobile apps use the popular JPEG format to display their images and user uploaded photos. The JPEG format has efficient built-in compression that reduces image size while maintaining a reasonable visual quality. But you can reach much better results using more modern image file formats.

A few years ago Google introduced the WebP image format, which is supported mainly by the popular Chrome browser. Cloudinary, a cloud-based image management platform, has supported automatic conversion to the WebP format for some time, and this has proved to be extremely useful in reducing image file size while ensuring the resulting images look great.

In 2009, Microsoft introduced its own modern image format. It is called JPEG-XR, and has been supported by Internet Explorer since version 9. The JPEG-XR format allows saving and delivering high quality photos using significantly less bytes. This format supports both lossy and lossless compression, and includes an alpha channel for supporting semi-transparent pixels.

In this blog post we show how Cloudinary’s cloud service can convert images on-the-fly to the JPEG-XR format, with automatic delivery of JPEG-XR images to users of supported browsers.

On-the-fly JPEG-XR conversion

The following photo was uploaded to Cloudinary, and assigned the identifier seagull. The original image is a 1,000x667 JPEG photo, and it weighs 107KB. Note that in the sample images below we show 500x334 scaled-down versions so they fit better in this post.

Ruby:
Copy to clipboard
cl_image_tag("seagull.jpg")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.jpg")
PHP v2:
Copy to clipboard
(new ImageTag('seagull.jpg'));
Python:
Copy to clipboard
CloudinaryImage("seagull.jpg").image()
Node.js:
Copy to clipboard
cloudinary.image("seagull.jpg")
Java:
Copy to clipboard
cloudinary.url().imageTag("seagull.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.jpg').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.jpg")
React:
Copy to clipboard
<Image publicId="seagull.jpg" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.jpg" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.jpg" >

</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("seagull.jpg")
Android:
Copy to clipboard
MediaManager.get().url().generate("seagull.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("seagull.jpg")!, cloudinary: cloudinary)
Seagull JPEG
107KB JPEG

Cloudinary makes it possible to modify images on-the-fly using dynamic URLs with parameters that define image manipulations. Simply setting the format parameter in the URL to the desired file type, or changing the file extension to the image URL, instructs Cloudinary to convert the image and display it to users in the target format.

The JPEG-XR format has multiple possible file extensions: .jxr, .hdp and .wdp. The latter is the commonly used one. Setting the format parameter or the URL's file extension to wdp tells Cloudinary to convert the original image to the JPEG-XR format.

Ruby:
Copy to clipboard
cl_image_tag("seagull.wdp")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.wdp")
PHP v2:
Copy to clipboard
(new ImageTag('seagull.wdp'));
Python:
Copy to clipboard
CloudinaryImage("seagull.wdp").image()
Node.js:
Copy to clipboard
cloudinary.image("seagull.wdp")
Java:
Copy to clipboard
cloudinary.url().imageTag("seagull.wdp");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.wdp').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.wdp")
React:
Copy to clipboard
<Image publicId="seagull.wdp" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.wdp" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.wdp" >

</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("seagull.wdp")
Android:
Copy to clipboard
MediaManager.get().url().generate("seagull.wdp");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("seagull.wdp")!, cloudinary: cloudinary)
Seagull JPEG-XR
71KB JPEG-XR - Viewable only in IE 9+

The resulting WDP looks great and weighs only 71KB. This means that we saved 34% of the original file size.

Note that to see our sample JPEG-XR images, you should open this blog post in Internet Explorer.

Cropping, resizing and manipulating JPEG-XR images

Cloudinary supports a rich set of image manipulation capabilities that allow you to dynamically adapt your images to your site’s graphic design, and any desktop or mobile device. The following dynamic manipulation URL and sample code generates a 250x300 cropped version of the original seagull while increasing color saturation by 150%

Ruby:
Copy to clipboard
cl_image_tag("seagull.jpg", :width=>250, :height=>300, :effect=>"saturation:150", :crop=>"fill")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.jpg", array("width"=>250, "height"=>300, "effect"=>"saturation:150", "crop"=>"fill"))
PHP v2:
Copy to clipboard
(new ImageTag('seagull.jpg'))
  ->resize(Resize::fill()->width(250)->height(300))
  ->adjust(Adjust::saturation()->level(150));
Python:
Copy to clipboard
CloudinaryImage("seagull.jpg").image(width=250, height=300, effect="saturation:150", crop="fill")
Node.js:
Copy to clipboard
cloudinary.image("seagull.jpg", {width: 250, height: 300, effect: "saturation:150", crop: "fill"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(250).height(300).effect("saturation:150").crop("fill")).imageTag("seagull.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.jpg', {width: 250, height: 300, effect: "saturation:150", crop: "fill"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.jpg", {width: 250, height: 300, effect: "saturation:150", crop: "fill"})
React:
Copy to clipboard
<Image publicId="seagull.jpg" >
  <Transformation width="250" height="300" effect="saturation:150" crop="fill" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.jpg" >
  <cld-transformation width="250" height="300" effect="saturation:150" crop="fill" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.jpg" >
  <cl-transformation width="250" height="300" effect="saturation:150" crop="fill">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(250).Height(300).Effect("saturation:150").Crop("fill")).BuildImageTag("seagull.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(250).height(300).effect("saturation:150").crop("fill")).generate("seagull.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(250).setHeight(300).setEffect("saturation:150").setCrop("fill")).generate("seagull.jpg")!, cloudinary: cloudinary)
Seagull thumbnail JPEG
19.6KB JPEG

Setting the file format to wdp generates a JPEG-XR version of the same file. The resulting image looks almost identical to the original JPEG but weighs less.

Ruby:
Copy to clipboard
cl_image_tag("seagull.wdp", :width=>250, :height=>300, :effect=>"saturation:150", :crop=>"fill")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.wdp", array("width"=>250, "height"=>300, "effect"=>"saturation:150", "crop"=>"fill"))
PHP v2:
Copy to clipboard
(new ImageTag('seagull.wdp'))
  ->resize(Resize::fill()->width(250)->height(300))
  ->adjust(Adjust::saturation()->level(150));
Python:
Copy to clipboard
CloudinaryImage("seagull.wdp").image(width=250, height=300, effect="saturation:150", crop="fill")
Node.js:
Copy to clipboard
cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", crop: "fill"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(250).height(300).effect("saturation:150").crop("fill")).imageTag("seagull.wdp");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.wdp', {width: 250, height: 300, effect: "saturation:150", crop: "fill"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", crop: "fill"})
React:
Copy to clipboard
<Image publicId="seagull.wdp" >
  <Transformation width="250" height="300" effect="saturation:150" crop="fill" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.wdp" >
  <cld-transformation width="250" height="300" effect="saturation:150" crop="fill" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.wdp" >
  <cl-transformation width="250" height="300" effect="saturation:150" crop="fill">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(250).Height(300).Effect("saturation:150").Crop("fill")).BuildImageTag("seagull.wdp")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(250).height(300).effect("saturation:150").crop("fill")).generate("seagull.wdp");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(250).setHeight(300).setEffect("saturation:150").setCrop("fill")).generate("seagull.wdp")!, cloudinary: cloudinary)
Seagull thumbnail JPEG-XR
16.9KB JPEG-XR - Viewable only in IE 9+

Similar to JPEG, the JPEG-XR has a quality level you can control. While the default quality level is 70, you can set a custom quality level using the quality parameter (when constructing an image URL using Cloudinary’s client libraries), or q when constructing a URL directly. The following URL and sample code sets the JPEG-XR quality to 50:

Ruby:
Copy to clipboard
cl_image_tag("seagull.wdp", :width=>250, :height=>300, :effect=>"saturation:150", :quality=>50, :crop=>"fill")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.wdp", array("width"=>250, "height"=>300, "effect"=>"saturation:150", "quality"=>50, "crop"=>"fill"))
PHP v2:
Copy to clipboard
(new ImageTag('seagull.wdp'))
  ->resize(Resize::fill()->width(250)->height(300))
  ->adjust(Adjust::saturation()->level(150))
  ->delivery(Delivery::quality(50));
Python:
Copy to clipboard
CloudinaryImage("seagull.wdp").image(width=250, height=300, effect="saturation:150", quality=50, crop="fill")
Node.js:
Copy to clipboard
cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", quality: 50, crop: "fill"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(250).height(300).effect("saturation:150").quality(50).crop("fill")).imageTag("seagull.wdp");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.wdp', {width: 250, height: 300, effect: "saturation:150", quality: 50, crop: "fill"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", quality: 50, crop: "fill"})
React:
Copy to clipboard
<Image publicId="seagull.wdp" >
  <Transformation width="250" height="300" effect="saturation:150" quality="50" crop="fill" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.wdp" >
  <cld-transformation width="250" height="300" effect="saturation:150" quality="50" crop="fill" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.wdp" >
  <cl-transformation width="250" height="300" effect="saturation:150" quality="50" crop="fill">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(250).Height(300).Effect("saturation:150").Quality(50).Crop("fill")).BuildImageTag("seagull.wdp")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(250).height(300).effect("saturation:150").quality(50).crop("fill")).generate("seagull.wdp");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(250).setHeight(300).setEffect("saturation:150").setQuality(50).setCrop("fill")).generate("seagull.wdp")!, cloudinary: cloudinary)
Seagull JPEG-XR quality 50
10.9KB JPEG-XR 50% Quality - Viewable only in IE 9+

It's hard to tell the difference between the 50%-quality JPEG-XR and the higher quality image. This new file weighs only 10.9KB, saving 44% of the original JPEG file.

As mentioned above, the JPEG-XR format includes an alpha channel and supports semi-transparent pixels. This means you can use JPEG-XR to generate semi-transparent images and place them on non-white background. This will save image size and bandwidth because the image contains less pixels.

The following URL creates a circular shape around the same image, by setting the radius parameter to max. As you can see below, the JPEG result on the left has a white background, while the JPEG-XR image on the right has a transparent background. On Firefox, you’d be forced to use PNG for this semi-transparent image, which would have been approximately 10 times the size of this JPEG-XR.

Ruby:
Copy to clipboard
cl_image_tag("seagull.wdp", :width=>250, :height=>300, :effect=>"saturation:150", :radius=>"max", :crop=>"fill")
PHP v1:
Copy to clipboard
cl_image_tag("seagull.wdp", array("width"=>250, "height"=>300, "effect"=>"saturation:150", "radius"=>"max", "crop"=>"fill"))
PHP v2:
Copy to clipboard
(new ImageTag('seagull.wdp'))
  ->resize(Resize::fill()->width(250)->height(300))
  ->roundCorners(RoundCorners::max())
  ->adjust(Adjust::saturation()->level(150));
Python:
Copy to clipboard
CloudinaryImage("seagull.wdp").image(width=250, height=300, effect="saturation:150", radius="max", crop="fill")
Node.js:
Copy to clipboard
cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", radius: "max", crop: "fill"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(250).height(300).effect("saturation:150").radius("max").crop("fill")).imageTag("seagull.wdp");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.wdp', {width: 250, height: 300, effect: "saturation:150", radius: "max", crop: "fill"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.wdp", {width: 250, height: 300, effect: "saturation:150", radius: "max", crop: "fill"})
React:
Copy to clipboard
<Image publicId="seagull.wdp" >
  <Transformation width="250" height="300" effect="saturation:150" radius="max" crop="fill" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.wdp" >
  <cld-transformation width="250" height="300" effect="saturation:150" radius="max" crop="fill" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.wdp" >
  <cl-transformation width="250" height="300" effect="saturation:150" radius="max" crop="fill">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(250).Height(300).Effect("saturation:150").Radius("max").Crop("fill")).BuildImageTag("seagull.wdp")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(250).height(300).effect("saturation:150").radius("max").crop("fill")).generate("seagull.wdp");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(250).setHeight(300).setEffect("saturation:150").setRadius("max").setCrop("fill")).generate("seagull.wdp")!, cloudinary: cloudinary)

Seagull non-transparent JPEG Seagull semi-transparent JPEG-XR - Viewable only in IE 9+

                                                  JPEG                                                                       JPEG-XR (IE 9+ only)

Automatic delivery of JPEG-XR and WebP according to user browsers

Users are visiting your site or application using various browsers, but it’s likely that most of them are using either Chrome or Internet Explorer. Optimally, you would want every user to get the image that best matches the capabilities of their current browser. Cloudinary takes care of that automatically.

By setting the format parameter to auto, or f_auto for delivery URLs, Cloudinary dynamically delivers the best matching format: WebP for Chrome and supported Android browsers, JPEG-XR for supported Internet Explorer browsers, and JPEG for all other browsers. The relevant image format is delivered to users via fast CDN.

By dynamically selecting the image format, Cloudinary allows you to deliver high quality images with minimal bandwidth use, and with a very minimal development effort.

Ruby:
Copy to clipboard
cl_image_tag("seagull.jpg", :width=>250, :height=>250, :crop=>"fill", :fetch_format=>:auto)
PHP v1:
Copy to clipboard
cl_image_tag("seagull.jpg", array("width"=>250, "height"=>250, "crop"=>"fill", "fetch_format"=>"auto"))
PHP v2:
Copy to clipboard
(new ImageTag('seagull.jpg'))
  ->resize(Resize::fill()->width(250)->height(250))
  ->delivery(Delivery::format(Format::auto()));
Python:
Copy to clipboard
CloudinaryImage("seagull.jpg").image(width=250, height=250, crop="fill", fetch_format="auto")
Node.js:
Copy to clipboard
cloudinary.image("seagull.jpg", {width: 250, height: 250, crop: "fill", fetch_format: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(250).height(250).crop("fill").fetchFormat("auto")).imageTag("seagull.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('seagull.jpg', {width: 250, height: 250, crop: "fill", fetchFormat: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("seagull.jpg", {width: 250, height: 250, crop: "fill", fetch_format: "auto"})
React:
Copy to clipboard
<Image publicId="seagull.jpg" >
  <Transformation width="250" height="250" crop="fill" fetchFormat="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="seagull.jpg" >
  <cld-transformation width="250" height="250" crop="fill" fetchFormat="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="seagull.jpg" >
  <cl-transformation width="250" height="250" crop="fill" fetch-format="auto">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(250).Height(250).Crop("fill").FetchFormat("auto")).BuildImageTag("seagull.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(250).height(250).crop("fill").fetchFormat("auto")).generate("seagull.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(250).setHeight(250).setCrop("fill").setFetchFormat("auto")).generate("seagull.jpg")!, cloudinary: cloudinary)
Automatic format WebP, JPEG-XR and JPEG
Auto WebP/JPEG-XR/JPEG

The image above is displayed using different formats according to the user’s specific browser. A WebP image is dynamically shown to Chrome users, and a JPEG-XR image is shown to IE users, significantly saving bandwidth and improving user experience for both.

Summary

Image optimization has become a must for speeding load times of modern sites and apps. Modern and efficient image formats, like WebP and JPEG-XR provide a great solution that combines high visual quality with a high compression rate. However, because these formats are only supported by specific browsers, delivering them is a challenge for developers.

Cloudinary is a cloud-based image management service that aims to simplify image-related development work by taking care of all image-related activities on a website. As a dynamic JPEG-XR converter, which can deliver JPEG-XR to users with Internet Explorer, WebP for users of Chrome, and other image formats for other browsers, Cloudinary allows web developers to improve user experience with only a few lines of code. a very small effort.

Automatic conversion and delivery of the JPEG-XR format is available for all of Cloudinary's plans, including the free plan. If you already have a Cloudinary account and you use the f_auto parameter, JPEG-XR images are already automatically generated and delivered to your Internet Explorer users! Enjoy the reduced bandwidth and faster user experience.

Recent Blog Posts

Generate Waveform Images from Audio with Cloudinary

This is a reposting of an article written by David Walsh. Check out his blog HERE!
I've been working a lot with visualizations lately, which is a far cry from your normal webpage element interaction coding; you need advanced geometry knowledge, render and performance knowledge, and much more. It's been a great learning experience but it can be challenging and isn't always an interest of all web developers. That's why we use apps and services specializing in complex tasks like Cloudinary: we need it done quickly and by a tool written by an expert.

Read more
Make All Images on Your Website Responsive in 3 Easy Steps

Images are crucial to website performance, but most still don't implement responsive images. It’s not just about fitting an image on the screen, but also making the the image size relatively rational to the device. The srcset and sizes options, which are your best hit are hard to implement. Cloudinary provides an easier way, which we will discuss in this article.

Read more

The Future of Audio and Video on the Web

By Prosper Otemuyiwa
The Future of Audio and Video on the Web

Web sites and platforms are becoming increasingly media-rich. Today, approximately 62 percent of internet traffic is made up of images, with audio and video constituting a growing percentage of the bytes.

Read more

Embed Images in Email Campaigns at Scale

By Sourav Kundu
Embed Images in Email Campaigns at Scale

tl;dr

Cloudinary is a powerful image hosting solution for email marketing campaigns of any size. With features such as advanced image optimization and on-the-fly image transformation, backed by a global CDN, Cloudinary provides the base for a seamless user experience in your email campaigns leading to increased conversion and performance.

Read more
Build the Back-End For Your Own Instagram-style App with Cloudinary

Github Repo

Managing media files (processing, storage and manipulation) is one of the biggest challenges we encounter as practical developers. These challenges include:

A great service called Cloudinary can help us overcome many of these challenges. Together with Cloudinary, let's work on solutions to these challenges and hopefully have a simpler mental model towards media management.

Read more

Build A Miniflix in 10 Minutes

By Prosper Otemuyiwa
Build A Miniflix in 10 Minutes

Developers are constantly faced with challenges of building complex products every single day. And there are constraints on the time needed to build out the features of these products.

Engineering and Product managers want to beat deadlines for projects daily. CEOs want to roll out new products as fast as possible. Entrepreneurs need their MVPs like yesterday. With this in mind, what should developers do?

Read more