Cloudinary Blog

Image Optimization in Ruby

Image Optimization in Ruby

Image optimization is a science that involves reducing the size of an image while maintaining high visual quality with the help of different techniques and algorithms.

In this article, we’ll take a look at how to perform and implement image optimization in Ruby.

However, before we dive right in, let’s go through why image optimization is so important.

Webinar
How to Optimize for Page Load Speed

The Importance of Image Optimization

There are many reasons why you would want to optimize images. But let’s look at three of the main ones:

  • Bandwidth - Users actually take note of the amount of data they spend surfing different websites. Bandwidth costs money. Optimizing your images will save a lot of bandwidth, which reduces users’ costs of surfing your site and minimizes the costs of your hosting plan.
  • Download time - A user that is made to wait for several seconds or minutes for your page to load might not visit that page a second time. Not optimizing your images will make your web page load time increase, which in turn discourages users from visiting your platform.
  • Storage space - Reduced image sizes will automatically reduce the amount of storage space you need. Consider this typical scenario: A user uploads an image that is 5MB in size and, your website optimizes the image by reducing it to 2MB without losing the quality of the image. Storing 100 images of that size will require only 200MB of storage rather than 500MB at the original size. You have just shaved off 300MB of storage space.

In addition, you also have to deal with several factors about each image, including:

  1. Quality
  2. Format
  3. Metadata
  4. Size and resizing

Optimizing Images in Ruby

Piet

Piet is a gem that optimizes images. Under the hood, it uses optipng and jpegoptim. You can install it like so:

Copy to clipboard
gem install piet

You can use it:

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

This will optimize the image but output nothing. Add an option :verbose => true:

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

An output will be generated:

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)

You can use Piet to convert 24/32-bit PNG images to paletted (8-bit) PNGs. The conversion reduces file sizes significantly and preserves full alpha transparency:

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

Check out the documentation for more options.

Image_optim

This is a comprehensive optimization gem that takes advantage of several utilities, such as jhead, jpegoptim, jpeg-recompress, jpegtran, optipng, pngcrush, pngout, pngquant and others. Install the gem:

Copy to clipboard
gem install image_optim

In your ruby application, you can invoke it:

Copy to clipboard
image_optim = ImageOptim.new

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

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

And you can optimize an image:

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

Check the documentation for a wide range of options to use with the gem.

Mini_magick

This Ruby gem is a wrapper for ImageMagick. It gives you access to all ImageMagick options. Add the gem to your Gemfile like so:

Copy to clipboard
gem "mini_magick"

Resize an image:

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"

It makes a resized copy of the image. You can modify the original image by not calling the write method. Check out the documentation for more optimization options using mini_magick.

Cloudinary: An Easy Optimization Alternative

Using Cloudinary, you can quickly and easily optimize your images, regardless of the programming language. Cloudinary automatically performs certain optimizations on all transformed images by default. Its integrated, fast CDN delivery also helps to get all the image resources to your users quickly. Cloudinary offers:

Automatic quality and encoding: Using the q_auto parameter, the optimal quality compression level and optimal encoding settings are selected based on the specific image content, format and the viewing browser. The result is image with good visual quality and a reduced file size. 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

You also can use q_auto:best, q_auto:low, q_auto:good or q_auto:eco to adjust the visual quality of your images.

Automatic transformation: The f_auto parameter enables Cloudinary to analyze the image content and select the best format to deliver. For example, it can automatically deliver images as WebP to Chrome browsers or JPEG-XR to Internet Explorer browsers, while using the original format for all other browsers. Using both f_auto and q_auto, Cloudinary will still generally deliver WebP and JPEG-XR to the relevant browsers, but might deliver selected images as PNG-8 or PNG-24 if the quality algorithm determines that as optimal.

Resizing and cropping images with w and h parameters: Using the width and height parameters in URLs, you can resize the images with Cloudinary:

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

It maintains the aspect ratio, but resizes the image to whatever height and width you desire.

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 the following image cropping modes: scale, fit, mfit, fill, lfill, limit, pad, lpad, mpad, crop, thumb, imagga_crop and imagga_scale.

Conclusion

One of the best ways to increase page performance is via image optimization, so you will want to take some time to ensure that all your images are properly optimized and cached.

We have highlighted how to optimize images using the beautifully crafted language, Ruby, as well as with Cloudinary. But that’s just a tip of the iceberg, you can check out how to optimize your jpeg images without compromising quality for more ideas.

Cloudinary provides many options for optimizing your images. Feel free to dive in and explore them.

Further Reading on Image Optimization

Recent Blog Posts

Laravel File Upload to a Local Server Or to the Cloud

Currently, Laravel is the most renowned PHP framework, boasting of a large developer community; several open-source packages, such as Cashier, Sanctum, Scout, and Telescope; and a host of paid platforms, e.g., Laravel Forge, Envoyer, and Vapor. Laravel Forge & Envoyer ably supports deployment and use of Laravel production-based apps.

Read more
TedsVintageArt.com Automates Generation of Captivating Product Images on Cloudinary

At TedsVintageArt.com, we digitally restore historic maps and sell their art prints on multiple platforms, such as Amazon, Etsy, eBay, and Houzz. As our operations ramped up years ago, it took an inordinately long time to generate custom images for our products. Plus, since we sell art, it behooves us to produce multiple high-quality images for each print, which was another time-consuming task.

Read more
lastminute.com Takes a Vacation From Media-Management Headaches With Cloudinary

As a 20-year online leader in travel and leisure retail, Europe-based public company lastminute.com along with its 1,200 employees are committed to enriching the lives of vacationers through comprehensive and enticing products and services. Beyond flight deals and tours, it's the images and videos, whether of that luxury villa in Greece, romantic Parisian street, or exotic stroll through the Marrakech markets, that attract audiences and boost bookings.

Read more