Cloudinary Blog

Optimizing Images in Ruby

Optimizing Images in Ruby

Through various techniques and algorithms, you can optimize images, that is, reduce their file size yet still maintain a high visual quality. This article shows you how to optimally reduce image sizes in Ruby and Cloudinary.


How to Optimize for Page-Load Speed


The Importance of Image Optimization

Effective management of images involves taking into account four criteria: quality, size, format, and metadata, with quality and size a balancing act for optimization. Here are three major reasons why optimization counts:

  • Bandwidth. Bandwidth costs money both on your part as the site’s host and on your audience’s part. Optimizing images saves bandwidth.
  • Download time. Loading unoptimized images takes longer, and viewers who must wait for quite a while for a page to load might never return.
  • Storage space. Smaller images need less storage space. Consider this typical scenario: 100 user-uploaded images that weigh 5 MB each—and that you optimize to 2 MB each with no quality loss—require only 200 MB of storage instead of the original 500 MB.

Optimization of Images in Ruby

You can downsize images in Ruby with one of three gems: piet, image_optim, and mini_magick.

piet

To install **piet**, which optimizes images with the **optiPNG ** and **jpegoptim** utilities, type:

Copy to clipboard
gem install piet

For example, to optimize an image called dog.jpg in Ruby, type:

Copy to clipboard
Piet.optimize(‘/images/dog.jpg’)

To generate and display the related output, add the option :verbose => true:

Copy to clipboard
Piet.optimize('/images/dog.png', :verbose => true)

Here’s an output example:

Copy to clipboard
Processing: dog.png
340x340 pixels, 4x8 bits/pixel, RGB+alpha
Input IDAT size = 157369 bytes
Input file size = 157426 bytes

Trying:
  zc = 9  zm = 9  zs = 0  f = 1   IDAT size = 156966
  zc = 9  zm = 8  zs = 0  f = 1   IDAT size = 156932

Selecting parameters:
  zc = 9  zm = 8  zs = 0  f = 1   IDAT size = 156932

Output IDAT size = 156932 bytes (437 bytes decrease)
Output file size = 156989 bytes (437 bytes = 0.28% decrease)

Furthermore, you can convert 24- or 32-bit PNGs to paletted (8-bit) PNGs with piet, significantly reducing their sizes and preserving full-alpha transparency:

Copy to clipboard
Piet.pngquant('/a/path/where/you/store/the/file/to/convert')

For more options, see the related documentation.

image_optim

**image_optim** is a comprehensive gem that takes advantage of numerous utilities, such as jhead, jpegoptim, jpeg-recompress, jpegtran, optipng, pngcrush, pngout, and pngquant.

To install image_optim, type:

Copy to clipboard
gem install image_optim

Afterwards, to invoke image_optim In your Ruby app, type:

Copy to clipboard
image_optim = ImageOptim.new

image_optim = ImageOptim.new(:pngout => false)

image_optim = ImageOptim.new(:nice => 20)

Then, to optimize an image called dog.jpg, type:

Copy to clipboard
image_optim.optimize_image('dog.png')

For more options, see the related documentation.

mini_magick

With **mini_magick**(https://github.com/minimagick/minimagick), a wrapper for ImageMagick, you can access all ImageMagick options.

To add mini_magick to your Gemfile, type:

Copy to clipboard
gem "mini_magick"

To have mini_magick resize an image called dog.jpg as a copy of the original, type:

Copy to clipboard
image = MiniMagick::Image.open("dog.jpg")
image.path #=> "/var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/magick20140921-75881-1yho3zc.jpg"
image.resize "300x300"
image.format "png"
image.write "output.png"

Omitting the write method above enables you to modify the original image. For more options, see the related documentation.

Cloudinary: An Ideal Optimization Alternative

With Cloudinary, you can quickly and intuitively optimize images regardless of the programming language. By default and through automation, Cloudinary optimizes all transformed images, efficiently delivering the final version through integrated content delivery networks (CDNs). Among the many Cloudinary capabilities are the following:

Automated quality compression and encoding. Through the **q_auto** parameter, Cloudinary selects the optimal quality-compression level and encoding settings according to the image content, format, and viewing browser. The result is a sharp yet downsized image. For example:

Ruby:
Copy to clipboard
cl_image_tag("woman.jpg", :quality=>"auto")
PHP:
Copy to clipboard
cl_image_tag("woman.jpg", array("quality"=>"auto"))
Python:
Copy to clipboard
CloudinaryImage("woman.jpg").image(quality="auto")
Node.js:
Copy to clipboard
cloudinary.image("woman.jpg", {quality: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().quality("auto")).imageTag("woman.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('woman.jpg', {quality: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("woman.jpg", {quality: "auto"})
React:
Copy to clipboard
<Image publicId="woman.jpg" >
  <Transformation quality="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="woman.jpg" >
  <cld-transformation quality="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="woman.jpg" >
  <cl-transformation quality="auto">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Quality("auto")).BuildImageTag("woman.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().quality("auto")).generate("woman.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setQuality("auto")).generate("woman.jpg")!, cloudinary: cloudinary)
https://res.cloudinary.com/demo/image/upload/q_auto/woman.jpg

To adjust the visual quality of images, add the **q_auto:best**, **q_auto:low**, **q_auto:good**, or **q_auto:eco** parameter to the dynamic URL.

Automated transformation. The **f_auto** parameter enables Cloudinary to analyze the image content and then select the best format for delivery: for example, WebP for Chrome, JPEG-XR for Internet Explorer, and the original format for all other browsers.

A combination of f_auto and q_auto causes Cloudinary to still deliver WebP and JPEG-XR to the relevant browsers. However, if the quality algorithm determines that PNG-8 or PNG-24 is optimal for certain images, Cloudinary switches the delivery format to either of those two, as appropriate.

Image resizing and cropping with w and h parameters. By adding to URLs the width (w) and height (h) parameters along with the dimensions you desire, you instruct Cloudinary to resize the images accordingly but maintain the aspect ratio:

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :width=>0.5, :crop=>"scale")
PHP:
Copy to clipboard
cl_image_tag("sample.jpg", array("width"=>0.5, "crop"=>"scale"))
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(width=0.5, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {width: "0.5", crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(0.5).crop("scale")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {width: "0.5", crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {width: "0.5", crop: "scale"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="0.5" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="0.5" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="0.5" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(0.5).Crop("scale")).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(0.5).crop("scale")).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(0.5).setCrop("scale")).generate("sample.jpg")!, cloudinary: cloudinary)
https://res.cloudinary.com/demo/image/upload/w_0.5/sample.jpg

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :height=>200, :crop=>"scale")
PHP:
Copy to clipboard
cl_image_tag("sample.jpg", array("height"=>200, "crop"=>"scale"))
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(height=200, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {height: 200, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().height(200).crop("scale")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {height: 200, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {height: 200, crop: "scale"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation height="200" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation height="200" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation height="200" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Height(200).Crop("scale")).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().height(200).crop("scale")).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setHeight(200).setCrop("scale")).generate("sample.jpg")!, cloudinary: cloudinary)
https://res.cloudinary.com/demo/image/upload/h_200/sample.jpg

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :width=>200, :height=>100, :crop=>"scale")
PHP:
Copy to clipboard
cl_image_tag("sample.jpg", array("width"=>200, "height"=>100, "crop"=>"scale"))
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(width=200, height=100, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {width: 200, height: 100, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(200).height(100).crop("scale")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {width: 200, height: 100, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {width: 200, height: 100, crop: "scale"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="200" height="100" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="200" height="100" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="200" height="100" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(200).Height(100).Crop("scale")).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(200).height(100).crop("scale")).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(200).setHeight(100).setCrop("scale")).generate("sample.jpg")!, cloudinary: cloudinary)
https://res.cloudinary.com/demo/image/upload/w_200,h_100/sample.jpg

Cloudinary supports these image-cropping modes: scale, [fit](https://cloudinary.com/documentation/image_transformations#fit), mfit, fill, lfill, limit, pad, lpad, mpad, crop, thumb, imagga_crop, and imagga_scale.

Summary

Optimizing images is a priority task for enhancing page performance. The optimization procedures in Ruby and in Cloudinary, as described in this post, are just the tip of the iceberg. For more ideas, read this Cloudinary post and the related Cloudinary documentation.

Further Reading on Image Optimization

Recent Blog Posts

A New, Simple Tool for Creating Text Overlays for Images

Many Cloudinary users desire a UI for tasks like creating text overlays for images, which they then embed on webpages or download for marketing campaigns. Generating such overlays with the Cloudinary Media Library UI involves a bit of a learning curve, especially if they require multiple fonts or text lines, which even experienced users might find challenging to implement.

Read more
Transitioning JPEG-Based to JPEG XL-Based Images for Web Platforms

When the JPEG codec was being developed in the late 1980s, no standardized, lossy image-compression formats existed. JPEG became ready at exactly the right time in 1992, when the World Wide Web and digital cameras were about to become a thing. The introduction of HTML’s <img> tag in 1995 ensured the recognition of JPEG as the web format—at least for photographs. During the 1990s, digital cameras replaced analog ones and, given the limited memory capacities of that era, JPEG became the standard format for photography, especially for consumer-grade cameras.

Read more

Amplify Your Jamstack With Video

By Alex Patterson
Amplify Your Jamstack With Cloudinary Video

As defined by Amazon Web Services (AWS), Amplify is a set of products and tools with which mobile and front-end web developers can build and deploy AWS-powered, secure, and scalable full-stack apps. Also, you can efficiently configure their back ends, connect them to your app with just a few lines of code, and deploy static web apps in only three steps. Historically, because of their performance issues, managing images and videos is a daunting challenge for developers. Even though you can easily load media to an S3 bucket with AWS Amplify, transforming, compressing, and responsively delivering them is labor intensive and time consuming.

Read more
Cloudinary Helps Move James Hardie’s Experience Online

While COVID has affected most businesses, it has been particularly hard on those that sell products for the physical ‘brick and mortar’ world. One company that literally fits that bill is our Australian customer James Hardie, the largest global manufacturer of fibre cement products used in both domestic and commercial construction. These are materials that its buyers ideally want to see up close, in detail. When customers have questions, they expect personal service.

Read more