Cloudinary Blog

Smart Cropping, Intelligent Quality Selection, and Automated Responsive Images

Auto-Crop Images for Responsive Designs and Higher Quality

Every image is unique, so are website visitors. In a perfect world, we would adapt images to be "just right" for all users, i.e., perfectly cropped with responsive dimensions, correct encoding settings, and optimal quality in the most suitable format.

See this example of a photo of a cat:

Original cat photo

To have Cloudinary adapt and optimize that image to fit all devices and browsers through automation, add the parameters (in orange below) to the image URL:

Ruby:
Copy to clipboard
cl_image_tag("white_cat.jpg", :client_hints=>true, :transformation=>[
  {:aspect_ratio=>"4:6", :gravity=>"auto", :crop=>"fill"},
  {:quality=>"auto", :fetch_format=>:auto}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("white_cat.jpg", array("client_hints"=>true, "transformation"=>array(
  array("aspect_ratio"=>"4:6", "gravity"=>"auto", "crop"=>"fill"),
  array("quality"=>"auto", "fetch_format"=>"auto")
  )))
PHP v2:
Copy to clipboard
(new ImageTag('white_cat.jpg'))
  ->resize(Resize::fill()->aspectRatio('4:6')->gravity(Gravity::autoGravity()))
  ->delivery(Delivery::format(Format::auto()))
  ->delivery(Delivery::quality(Quality::auto()))
  ->clientHints(true);
Python:
Copy to clipboard
CloudinaryImage("white_cat.jpg").image(client_hints=True, transformation=[
  {'aspect_ratio': "4:6", 'gravity': "auto", 'crop': "fill"},
  {'quality': "auto", 'fetch_format': "auto"}
  ])
Node.js:
Copy to clipboard
cloudinary.image("white_cat.jpg", {client_hints: true, transformation: [
  {aspect_ratio: "4:6", gravity: "auto", crop: "fill"},
  {quality: "auto", fetch_format: "auto"}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .aspectRatio("4:6").gravity("auto").crop("fill").chain()
  .quality("auto").fetchFormat("auto")).clientHints(true).imageTag("white_cat.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('white_cat.jpg', {clientHints: true, transformation: [
  {aspectRatio: "4:6", gravity: "auto", crop: "fill"},
  {quality: "auto", fetchFormat: "auto"}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("white_cat.jpg", {client_hints: true, transformation: [
  {aspect_ratio: "4:6", gravity: "auto", crop: "fill"},
  {quality: "auto", fetch_format: "auto"}
  ]})
React:
Copy to clipboard
<Image publicId="white_cat.jpg" clientHints="true">
  <Transformation aspectRatio="4:6" gravity="auto" crop="fill" />
  <Transformation quality="auto" fetchFormat="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="white_cat.jpg" clientHints="true">
  <cld-transformation aspectRatio="4:6" gravity="auto" crop="fill" />
  <cld-transformation quality="auto" fetchFormat="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="white_cat.jpg" client-hints="true">
  <cl-transformation aspect-ratio="4:6" gravity="auto" crop="fill">
  </cl-transformation>
  <cl-transformation quality="auto" fetch-format="auto">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .AspectRatio("4:6").Gravity("auto").Crop("fill").Chain()
  .Quality("auto").FetchFormat("auto")).ClientHints(true).BuildImageTag("white_cat.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .aspectRatio("4:6").gravity("auto").crop("fill").chain()
  .quality("auto").fetchFormat("auto")).clientHints(true).generate("white_cat.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setAspectRatio("4:6").setGravity("auto").setCrop("fill").chain()
  .setQuality("auto").setFetchFormat("auto")).generate("white_cat.jpg")!, cloudinary: cloudinary)

Standard image crop and encoding Auto-crop images and encoding

The image on the left, a standard crop delivered as a standard JPEG of the original 2,000-px. height, is a large 537-KB file. In contrast, the image on the right is perfectly cropped and delivered as an optimized 170-KB WebP on Chrome, a bandwidth savings of 69 percent. You can save even more bandwidth by adopting one of our solutions for delivering responsive layouts, as described in the sections below.


Sign up for Cloudinary free today!


Optimal delivery on an image-by-image and user-by-user basis is challenging. It requires considerable knowhow of the intricacies of file formats, vision algorithms, and browser behavior. The challenge takes on phenomenal proportions if you must scale countless images that are uploaded to your websites and mobile apps. Automation is the ultimate answer.

The State of Images Solved

At its launch in 2012, Cloudinary, a complete image-management solution created by developers for developers, aimed at eliminating the R&D time required for managing images for web and mobile apps. A major milestone was reached in 2016 with the announcement of the state of Images Solved.

By way of background, developers must frequently create the perfect image crop that focuses on the most important region by first determining the optimal file format and encoder settings to represent the content with the minimum number of bytes. That means creating multiple variants of every image in different resolutions for responsive delivery on various devices.

Images Solved at Cloudinary automates the process of transforming images in a content-aware and context-aware manner. That is, for every high-resolution, user-uploaded image:

  1. Adapt it in real time to focus on its most important region.
  2. Dynamically select and incorporate the optimal quality and encoding settings.
  3. Responsively deliver the image to any device in any resolution or pixel density.

Further simplifying the life of developers are the following critical image-manipulation and delivery tasks performed through automation by Cloudinary:

  • AI and Saliency based automated cropping: g_auto
  • Content-aware encoding: q_auto
  • Dynamic format selection: f_auto
  • Automatic responsive images: w_auto and dpr_auto

Automated Cropping: g_auto

Simply scaling images up or down on websites, especially responsive ones, usually doesn’t cut it. Oftentimes, you must crop images to fit device layouts, resolutions, and aspect ratios while highlighting the important regions within the images. Manually doing all that is impracticable, especially if your app includes massive user-generated content and a dynamic responsive layout. Also, cropping images the default way, i.e., focusing on the center of the image, can result in loss of important content.

You can crop photos with Cloudinary’s face-detection capability, but what if you want to focus on more than just the face or if the image subject is a product, a food item, or a pet? Enter Cloudinary’s automated cropping feature, which, through a combination of an AI-based algorithm and a saliency algorithm, automatically detects an image’s region of interest and then crops it on the fly with dynamic URLs to fit your site’s design and layout when viewed on any device.

For example, this uploaded photo must fit into three webpages: one in landscape mode (e.g., 800x200), one in portrait mode (e.g., 300x600), and one as a square (e.g., 300x300):

Original uploaded photo

Standard center-cropping produces problematic results, with most of the cat hidden:

Regular portrait image cropping
Standard image cropping
Regular square image crop

Setting the gravity image-cropping parameter to auto or adding g_auto to the URL generates optimal cropping, displaying the cat in full:

Ruby:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", :width=>300, :height=>600, :gravity=>"auto", :crop=>"fill")
PHP v1:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", array("width"=>300, "height"=>600, "gravity"=>"auto", "crop"=>"fill"))
PHP v2:
Copy to clipboard
(new ImageTag('sofa_cat.jpg'))
  ->resize(Resize::fill()->width(300)->height(600)
    ->gravity(Gravity::autoGravity()));
Python:
Copy to clipboard
CloudinaryImage("sofa_cat.jpg").image(width=300, height=600, gravity="auto", crop="fill")
Node.js:
Copy to clipboard
cloudinary.image("sofa_cat.jpg", {width: 300, height: 600, gravity: "auto", crop: "fill"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(300).height(600).gravity("auto").crop("fill")).imageTag("sofa_cat.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sofa_cat.jpg', {width: 300, height: 600, gravity: "auto", crop: "fill"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sofa_cat.jpg", {width: 300, height: 600, gravity: "auto", crop: "fill"})
React:
Copy to clipboard
<Image publicId="sofa_cat.jpg" >
  <Transformation width="300" height="600" gravity="auto" crop="fill" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sofa_cat.jpg" >
  <cld-transformation width="300" height="600" gravity="auto" crop="fill" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sofa_cat.jpg" >
  <cl-transformation width="300" height="600" gravity="auto" crop="fill">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Height(600).Gravity("auto").Crop("fill")).BuildImageTag("sofa_cat.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(300).height(600).gravity("auto").crop("fill")).generate("sofa_cat.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(300).setHeight(600).setGravity("auto").setCrop("fill")).generate("sofa_cat.jpg")!, cloudinary: cloudinary)

Automatic portrait image cropping
Intelligent image cropping
Automatic square image crop

Note that Cloudinary generated the images above with the popular fill crop mode, retaining as much of the originals as feasible. However, to emphasize the object, websites sometimes prefer to display a zoomed-in thumbnail. Take these uploaded images:

Cat photo Car photo Red bike photo

To create a 300x270 thumbnail for each of the images, set gravity to face (g_face) in the URL to leverage Cloudinary’s face-detection feature. Here are the dynamically created, cloud-based versions:

Ruby:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", :width=>300, :height=>270, :gravity=>"face", :crop=>"thumb")
PHP v1:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", array("width"=>300, "height"=>270, "gravity"=>"face", "crop"=>"thumb"))
PHP v2:
Copy to clipboard
(new ImageTag('sofa_cat.jpg'))
  ->resize(Resize::thumbnail()->width(300)->height(270)
    ->gravity(Gravity::focusOn(FocusOn::face())));
Python:
Copy to clipboard
CloudinaryImage("sofa_cat.jpg").image(width=300, height=270, gravity="face", crop="thumb")
Node.js:
Copy to clipboard
cloudinary.image("sofa_cat.jpg", {width: 300, height: 270, gravity: "face", crop: "thumb"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(300).height(270).gravity("face").crop("thumb")).imageTag("sofa_cat.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sofa_cat.jpg', {width: 300, height: 270, gravity: "face", crop: "thumb"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sofa_cat.jpg", {width: 300, height: 270, gravity: "face", crop: "thumb"})
React:
Copy to clipboard
<Image publicId="sofa_cat.jpg" >
  <Transformation width="300" height="270" gravity="face" crop="thumb" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sofa_cat.jpg" >
  <cld-transformation width="300" height="270" gravity="face" crop="thumb" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sofa_cat.jpg" >
  <cl-transformation width="300" height="270" gravity="face" crop="thumb">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Height(270).Gravity("face").Crop("thumb")).BuildImageTag("sofa_cat.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(300).height(270).gravity("face").crop("thumb")).generate("sofa_cat.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(300).setHeight(270).setGravity("face").setCrop("thumb")).generate("sofa_cat.jpg")!, cloudinary: cloudinary)

Face detection based cropped thumbnail Face detection based cropped thumbnail Face detection based cropped thumbnail

The above thumbnails are passable. However, the blurry sofa in one overshadows the cat; the dog next to the lady in the top-right thumbnail is barely visible; and the red bike in the bottom one is completely hidden.

For a solution, leverage Cloudinary's thumbnail-generation mode, which intelligently analyzes the image content and focuses on the region of interest. Setting the crop mode to thumb and gravity to auto (c_thumb,g_auto) produces the thumbnails below, effectively conveying the theme of each of the photos.

Ruby:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", :width=>300, :height=>270, :gravity=>"auto", :crop=>"thumb")
PHP v1:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", array("width"=>300, "height"=>270, "gravity"=>"auto", "crop"=>"thumb"))
PHP v2:
Copy to clipboard
(new ImageTag('sofa_cat.jpg'))
  ->resize(Resize::thumbnail()->width(300)->height(270)
    ->gravity(Gravity::autoGravity()));
Python:
Copy to clipboard
CloudinaryImage("sofa_cat.jpg").image(width=300, height=270, gravity="auto", crop="thumb")
Node.js:
Copy to clipboard
cloudinary.image("sofa_cat.jpg", {width: 300, height: 270, gravity: "auto", crop: "thumb"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(300).height(270).gravity("auto").crop("thumb")).imageTag("sofa_cat.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sofa_cat.jpg', {width: 300, height: 270, gravity: "auto", crop: "thumb"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sofa_cat.jpg", {width: 300, height: 270, gravity: "auto", crop: "thumb"})
React:
Copy to clipboard
<Image publicId="sofa_cat.jpg" >
  <Transformation width="300" height="270" gravity="auto" crop="thumb" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sofa_cat.jpg" >
  <cld-transformation width="300" height="270" gravity="auto" crop="thumb" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sofa_cat.jpg" >
  <cl-transformation width="300" height="270" gravity="auto" crop="thumb">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Height(270).Gravity("auto").Crop("thumb")).BuildImageTag("sofa_cat.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(300).height(270).gravity("auto").crop("thumb")).generate("sofa_cat.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(300).setHeight(270).setGravity("auto").setCrop("thumb")).generate("sofa_cat.jpg")!, cloudinary: cloudinary)

Automatically cropped thumbnail Smartly cropped thumbnail Intelligently cropped thumbnail

In addition, you can fine-tune the g_auto algorithm. For details, see the related documentation.

Have a try of Cloudinary’s interactive demo of smart, automated cropping.image_transformations#automatic_cropping).

Intelligent Content-Aware Encoding: q_auto

A common concern for image edits is degradation of the visual quality, but quality loss is by far not always the case. In fact, precise adjustment of the compression level complemented by fine-tuning of the encoding settings can significantly reduce file size without any noticeable degradation. No single, optimal setting exists, though, because it depends on the compression algorithm and the image format and content.

Cloudinary automates the trade-off decision for file size versus quality on the fly with perceptual metrics and heuristics. The intelligent encoding algorithm analyzes the image to determine the best quality-compression level and the optimal encoding settings based on the image content. The result is a perceptually fine, size-minimized image.

To take advantage of Cloudinary’s automated capability for determining optimal encoding settings and the quality level for compression, set the quality manipulation parameter to auto (q_auto in URLs).

For example, the following JPEG image, downscaled to 500-px.-wide, weighs 57.88 KB:

Ruby:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", :width=>500, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", array("width"=>500, "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('cld_popsicles.jpg'))
  ->resize(Resize::scale()->width(500));
Python:
Copy to clipboard
CloudinaryImage("cld_popsicles.jpg").image(width=500, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("cld_popsicles.jpg", {width: 500, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).crop("scale")).imageTag("cld_popsicles.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('cld_popsicles.jpg', {width: 500, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("cld_popsicles.jpg", {width: 500, crop: "scale"})
React:
Copy to clipboard
<Image publicId="cld_popsicles.jpg" >
  <Transformation width="500" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="cld_popsicles.jpg" >
  <cld-transformation width="500" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="cld_popsicles.jpg" >
  <cl-transformation width="500" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Crop("scale")).BuildImageTag("cld_popsicles.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).crop("scale")).generate("cld_popsicles.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setCrop("scale")).generate("cld_popsicles.jpg")!, cloudinary: cloudinary)
Encoded JPEG of quality-level 90

This image, generated with q_auto, passes muster, weighing only 39.21 KB, which is 32 percent lighter!

Ruby:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", :width=>500, :quality=>"auto", :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", array("width"=>500, "quality"=>"auto", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('cld_popsicles.jpg'))
  ->resize(Resize::scale()->width(500))
  ->delivery(Delivery::quality(Quality::auto()));
Python:
Copy to clipboard
CloudinaryImage("cld_popsicles.jpg").image(width=500, quality="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("cld_popsicles.jpg", {width: 500, quality: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).quality("auto").crop("scale")).imageTag("cld_popsicles.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('cld_popsicles.jpg', {width: 500, quality: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("cld_popsicles.jpg", {width: 500, quality: "auto", crop: "scale"})
React:
Copy to clipboard
<Image publicId="cld_popsicles.jpg" >
  <Transformation width="500" quality="auto" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="cld_popsicles.jpg" >
  <cld-transformation width="500" quality="auto" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="cld_popsicles.jpg" >
  <cl-transformation width="500" quality="auto" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Quality("auto").Crop("scale")).BuildImageTag("cld_popsicles.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).quality("auto").crop("scale")).generate("cld_popsicles.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setQuality("auto").setCrop("scale")).generate("cld_popsicles.jpg")!, cloudinary: cloudinary)
JPEG generated with the automated quality parameter

Some cases require further fine-tuning of the quality-selection algorithm. For instance, you can apply a more aggressive compression algorithm with the q_auto:low option, which results in a 22.51 KB image: -

Ruby:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", :width=>500, :quality=>"auto:low", :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", array("width"=>500, "quality"=>"auto:low", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('cld_popsicles.jpg'))
  ->resize(Resize::scale()->width(500))
  ->delivery(Delivery::quality(Quality::autoLow()));
Python:
Copy to clipboard
CloudinaryImage("cld_popsicles.jpg").image(width=500, quality="auto:low", crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("cld_popsicles.jpg", {width: 500, quality: "auto:low", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).quality("auto:low").crop("scale")).imageTag("cld_popsicles.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('cld_popsicles.jpg', {width: 500, quality: "auto:low", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("cld_popsicles.jpg", {width: 500, quality: "auto:low", crop: "scale"})
React:
Copy to clipboard
<Image publicId="cld_popsicles.jpg" >
  <Transformation width="500" quality="auto:low" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="cld_popsicles.jpg" >
  <cld-transformation width="500" quality="auto:low" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="cld_popsicles.jpg" >
  <cl-transformation width="500" quality="auto:low" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Quality("auto:low").Crop("scale")).BuildImageTag("cld_popsicles.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).quality("auto:low").crop("scale")).generate("cld_popsicles.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setQuality("auto:low").setCrop("scale")).generate("cld_popsicles.jpg")!, cloudinary: cloudinary)
JPEG generated with the automated quality eco parameter

For more details on the q_auto fine-tuning options, see the related documentation.

As effective and recommendable as Cloudinary’s automatic quality-algorithm is, you can go the manual route by setting an absolute value (between 1 and 100) for the quality level. See this example:

Ruby:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", :width=>500, :quality=>80, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("cld_popsicles.jpg", array("width"=>500, "quality"=>80, "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('cld_popsicles.jpg'))
  ->resize(Resize::scale()->width(500))
  ->delivery(Delivery::quality(80));
Python:
Copy to clipboard
CloudinaryImage("cld_popsicles.jpg").image(width=500, quality=80, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("cld_popsicles.jpg", {width: 500, quality: 80, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).quality(80).crop("scale")).imageTag("cld_popsicles.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('cld_popsicles.jpg', {width: 500, quality: 80, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("cld_popsicles.jpg", {width: 500, quality: 80, crop: "scale"})
React:
Copy to clipboard
<Image publicId="cld_popsicles.jpg" >
  <Transformation width="500" quality="80" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="cld_popsicles.jpg" >
  <cld-transformation width="500" quality="80" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="cld_popsicles.jpg" >
  <cl-transformation width="500" quality="80" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Quality(80).Crop("scale")).BuildImageTag("cld_popsicles.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).quality(80).crop("scale")).generate("cld_popsicles.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setQuality(80).setCrop("scale")).generate("cld_popsicles.jpg")!, cloudinary: cloudinary)
JPEG generated with a low quality level of 50

As additional reference, check out Cloudinary’s interactive demo on the automated quality-transformation feature and the related documentation.

Dynamic Format Selection: f_auto

Image formats can significantly affect page-load time and bandwidth, e.g., modern formats like WebP can reduce image sizes by 30 percent, leading to faster page loads, more site engagement, and higher conversion rates. A common developer task is to pick the optimal image formats for various scenarios based on the image content and the viewing device or browser, e.g., JPEG for captured photos or for faster loading, and PNG for illustrations or pictures with a transparent background. For Chrome, Safari, Internet Explorer, and Edge browsers, you must take into account additional logic for modern formats like WebP and JPEG-XR.

As simple as the requirements for browsers and format compatibility might be, manually computing the format logic for a large volume of images is complex and inefficient. Instead, turn to Cloudinary, which can dynamically select and convert images to the most efficient format according to the content and viewing browser, delivering, for example, images in WebP to Chrome, JPEG-XR to Internet Explorer or Edge, and JPEG-2000 for Safari.

In addition to transparent WebP delivery and JPEG-XR delivery, you can combine Cloudinary’s automated capabilities for selecting the best format, encoding images, and setting the optimal quality level. For example, with the q_auto,f_auto parameters, Cloudinary would encode the picture of the cat as a 15.67-KB WebP for Chrome, a JPEG-XR for Internet Explorer and Edge, a JPEG-2000 for Safari, and a JPEG for other browsers.

Ruby:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", :width=>750, :quality=>"auto", :fetch_format=>:auto, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("sofa_cat.jpg", array("width"=>750, "quality"=>"auto", "fetch_format"=>"auto", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('sofa_cat.jpg'))
  ->resize(Resize::scale()->width(750))
  ->delivery(Delivery::format(Format::auto()))
  ->delivery(Delivery::quality(Quality::auto()));
Python:
Copy to clipboard
CloudinaryImage("sofa_cat.jpg").image(width=750, quality="auto", fetch_format="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("sofa_cat.jpg", {width: 750, quality: "auto", fetch_format: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(750).quality("auto").fetchFormat("auto").crop("scale")).imageTag("sofa_cat.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sofa_cat.jpg', {width: 750, quality: "auto", fetchFormat: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sofa_cat.jpg", {width: 750, quality: "auto", fetch_format: "auto", crop: "scale"})
React:
Copy to clipboard
<Image publicId="sofa_cat.jpg" >
  <Transformation width="750" quality="auto" fetchFormat="auto" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sofa_cat.jpg" >
  <cld-transformation width="750" quality="auto" fetchFormat="auto" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sofa_cat.jpg" >
  <cl-transformation width="750" quality="auto" fetch-format="auto" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(750).Quality("auto").FetchFormat("auto").Crop("scale")).BuildImageTag("sofa_cat.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(750).quality("auto").fetchFormat("auto").crop("scale")).generate("sofa_cat.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(750).setQuality("auto").setFetchFormat("auto").setCrop("scale")).generate("sofa_cat.jpg")!, cloudinary: cloudinary)
An image generated through automated format and quality selection

Combining q_auto and f_auto delivers a more sophisticated result than setting only one of those two parameters. A case in point: the Cloudinary algorithm might pick PNG or lossless WebP for images that contain drawings, and PNG8 or PNG24 if the quality algorithm finds it to be optimal for an ideal display and a small file size.

This URL dynamically generates a 500-px.-wide JPEG version of a drawing with the image-encoding and quality-selection parameter(q_auto without f_auto):

Ruby:
Copy to clipboard
cl_image_tag("flowers_and_birds.jpg", :width=>500, :quality=>"auto", :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("flowers_and_birds.jpg", array("width"=>500, "quality"=>"auto", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('flowers_and_birds.jpg'))
  ->resize(Resize::scale()->width(500))
  ->delivery(Delivery::quality(Quality::auto()));
Python:
Copy to clipboard
CloudinaryImage("flowers_and_birds.jpg").image(width=500, quality="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("flowers_and_birds.jpg", {width: 500, quality: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).quality("auto").crop("scale")).imageTag("flowers_and_birds.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('flowers_and_birds.jpg', {width: 500, quality: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("flowers_and_birds.jpg", {width: 500, quality: "auto", crop: "scale"})
React:
Copy to clipboard
<Image publicId="flowers_and_birds.jpg" >
  <Transformation width="500" quality="auto" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="flowers_and_birds.jpg" >
  <cld-transformation width="500" quality="auto" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="flowers_and_birds.jpg" >
  <cl-transformation width="500" quality="auto" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Quality("auto").Crop("scale")).BuildImageTag("flowers_and_birds.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).quality("auto").crop("scale")).generate("flowers_and_birds.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setQuality("auto").setCrop("scale")).generate("flowers_and_birds.jpg")!, cloudinary: cloudinary)
Cartoon encoded with Cloudinary’s automated quality-selection capability

The above JPEG weighs 41 KB. A careful look would reveal that the lossy nature of JPEG produced a few undesirable artifacts. Adding both q_auto and f_auto to the URL causes the algorithm to encode the image with PNG8, generating an artifact-free image that weighs only 34.3 KB. (The only artifacts are from the original high-quality JPEG.)

Ruby:
Copy to clipboard
cl_image_tag("flowers_and_birds.jpg", :width=>500, :quality=>"auto", :fetch_format=>:auto, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("flowers_and_birds.jpg", array("width"=>500, "quality"=>"auto", "fetch_format"=>"auto", "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('flowers_and_birds.jpg'))
  ->resize(Resize::scale()->width(500))
  ->delivery(Delivery::format(Format::auto()))
  ->delivery(Delivery::quality(Quality::auto()));
Python:
Copy to clipboard
CloudinaryImage("flowers_and_birds.jpg").image(width=500, quality="auto", fetch_format="auto", crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("flowers_and_birds.jpg", {width: 500, quality: "auto", fetch_format: "auto", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(500).quality("auto").fetchFormat("auto").crop("scale")).imageTag("flowers_and_birds.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('flowers_and_birds.jpg', {width: 500, quality: "auto", fetchFormat: "auto", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("flowers_and_birds.jpg", {width: 500, quality: "auto", fetch_format: "auto", crop: "scale"})
React:
Copy to clipboard
<Image publicId="flowers_and_birds.jpg" >
  <Transformation width="500" quality="auto" fetchFormat="auto" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="flowers_and_birds.jpg" >
  <cld-transformation width="500" quality="auto" fetchFormat="auto" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="flowers_and_birds.jpg" >
  <cl-transformation width="500" quality="auto" fetch-format="auto" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(500).Quality("auto").FetchFormat("auto").Crop("scale")).BuildImageTag("flowers_and_birds.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(500).quality("auto").fetchFormat("auto").crop("scale")).generate("flowers_and_birds.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(500).setQuality("auto").setFetchFormat("auto").setCrop("scale")).generate("flowers_and_birds.jpg")!, cloudinary: cloudinary)
Cartoon encoded with Cloudinary’s automated format-selection capability

For more details, see the related documentation.

 

Responsive Images Generated Through Automation: w_auto and dpr_auto

Responsive designs require multiple versions of every image for a sharp display on all devices and at all resolutions, pixel densities, and orientations. Editing, generating, managing, and delivering numerous image versions is a daunting task. Not so with Cloudinary, which dynamically delivers images for responsive websites on Retina and regular displays by automating the image width and determining the DPR value based on the viewing device, display size, and layout.

Cloudinary comes to the rescue by determining the image width based on the browser's viewport or layout width, subsequently computing the image’s optimal resolution for display on that device. Furthermore, Cloudinary can dynamically set image-specific breakpoints by determining how many image versions are required to balance the trade-off between optimal dimensions and bandwidth reduction.

All you need to do is upload a high-resolution version of your images to Cloudinary and make use of either JavaScript or Client Hints to have Cloudinary generate responsive images through automation.

Important: Due to privacy concerns on Client Hints’ potential for tracking users across websites, desktop Chrome 67 has temporarily stopped sending Client Hints, which still work on mobile Chrome, however.

After choosing the one of the above solutions, you can, through dynamic URLs, adapt images to fit the viewport, layout, and resolution on any device, ensuring a seamless display and optimal performance. To have Cloudinary choose and retrieve the images with best-fitting widths and DPR values, add to the dynamic URL the w and dpr parameters set to auto (dpr_auto,w_auto).

By default, Cloudinary rounds up the device's DPR to an integer value (1.0, 2.0, 3.0, etc.), and the required width to the closest multiple of 100 px.

Note these two caveats, however:

  • One image cannot accommodate all screen resolutions and devices.
  • Generating an image for every pixel change in width is overkill, yet producing one for every 100-px. difference might be arbitrary.

Therefore, you can fine-tune breakpoints:

Summary

The four image-automation capabilities described in this post, which promise to be extremely useful for web developers, are available in all Cloudinary plans, including the free plan. Do try out the capabilities and let us know what you think. From my personal experience, once you start using them, you’ll be hard pressed to recall how you manually transformed images before.

Note

  • Currently, the parameter for responsive breakpoints (w_auto:breakpoints) requires a custom domain name (CNAME) or private CDN distribution, which is available in Cloudinary's Advanced and higher plans. This feature might also incur additional costs.
  • As intelligent as automatic algorithms are, they are not perfect, let alone that the quality of the result might be subjective. As an alternative, configure a manual override through the Cloudinary API or UI, i.e., override automated image-cropping with custom coordinates and automated computation of the quality level with a custom level. Such overrides are valuable input for future enhancements of our algorithms.

References on Responsive Images

Recent Blog Posts

WebPerf, Media Optimization, and Core Web Vitals

Optimized media assets have always been essential to website performance. To help developers measure, understand and improve website performance, Google created Core Web Vitals, a subset of Web Vitals that focuses on three aspects of the user experience: loading, interactivity, and visual stability. In June 2021, Google plans to make page experience a ranking factor—so Core Web Vitals and media asset optimization will become even more important.

Read more
Auto-Tag Videos With Cloudinary: A Tutorial

Video is one of the best ways for capturing audience attention. Product demonstrations, property tours, tutorials, and keynotes all make great content—provided that they’re readily searchable by your team and visitors alike. Even though tagging and categorization help organize videos and make them easy to find, the labeling process is labor intensive, taking time away from key tasks like creating new videos.

Read more
Video Uploads With Cloudinary

Setting up the infrastructure for video uploads can go from straightforward to complex real fast. Why? Because many challenges are involved in building a foolproof service for an efficient and smooth process.

Read more
Optimize Media to Get Ready for Google’s Core Web Vitals

For years, Google has been updating its search algorithm to prioritize end-user experience, displaying the most relevant and helpful content at the top of search results. The latest—and maybe the most significant—update so far is Core Web Vitals (CWVs), which are new metrics announced a year ago that will, starting in June, begin determining search rankings. With this update, Google is being abundantly clear that visual experience of webpages is paramount.

Read more
Compressing, Resizing, and Optimizing Videos in Laravel

Videos are large media files—in most cases, at least four times larger than images—and are often created for ads, marketing campaigns, and instructional content to convey as much information as possible in a short time. Ensuring that videos do not buffer all the time and that the user’s data is protected from rapid consumption due to heavy page weight must be the modus operandi for all website builders and e-business owners.

Read more