Transforming Images

Specifying a default transformation

An application-wide default image transformation setting lets you specify the maximum dimensions all images may have on delivery. To specify this maximum is particularly recommendable if your editors tend to upload way-too-large images, or if you are making heavy use of images on most of your pages.

The default transformation is a configuration setting. The fit: :resize option can be omitted because it's the default:

Copy
Scrivito.configure do |config|
  config.default_image_transformation = { 
    width: 2000, height: 2000
  }
end

The above definition ensures that the height as well as the width of all images never exceeds 2000 pixels. When transforming images, Scrivito always adheres to the following rules:

  • Without a default, heigth + width <= 4096 applies (image dimensions are reduced if required).
  • Images with a file size larger than 8 MB are not transformed.
  • Smaller images are not scaled up.
  • Resizing preserves the aspect ratio.
  • All metadata is automatically stripped.
  • With lossy image formats, resizing involves quality reduction to 75 % as a default. You can change this using the quality: q option where q is in the range from 0 to 100.

Note that, if desired, you can disable image transformation completely by setting default_image_transformation to false. This also suppresses the removal of metadata from images. If you don't want any kind of transformation to be applied but still want metadata to be stripped, use an empty transformation specification.

Generating thumbnails

Do you need thumbnails for an image gallery? This can be easily accomplished by adding the following to the view, e.g. the show view of a widget:

Copy
<%= scrivito_image_tag widget, :image, {}, transform: {
  height: 120, width: 120, fit: :crop
} %>

If (and only if) both image dimensions are larger than those of the target area, the image is scaled down prior to cropping, keeping its aspect ratio and making it completely fill the area. Otherwise, the image is not scaled. In the next step, the image parts exceeding the given area are removed.

The part of the image to focus on when cropping can be specified using the crop option which can be set to left, right, top, bottom and center. We'll make this editable in the next section.

The images below illustrate how a picture in landscape orientation is treated to produce square thumbnails. Since, after rescaling, the image height exactly matches the target area height, the top and bottom cropping focus would have the same effect as focusing on the center.

Full size image to be transformed into a square thumbnail using cropping

Cropping focus: left

Cropping focus: center

Cropping focus: right

Making the cropping focus editable

Automated cropping only makes sense if the information to keep is in the same area for all images. If not, website editors should be given a means to specify this area. Assuming that you are using image widgets on your pages, you can adapt the model and the views to make setting the cropping focus an option. Extend the model so that it includes an attribute for specifying and a method for determining the cropping focus:

Copy
class ImageWidget < Widget
  attribute :image, :reference
  attribute :crop_focus, :enum,
    values: %w[center top right left bottom],
    default: 'center'

  def crop_focus
    self[:crop_focus] || 'center'
  end
end

Now make the cropping focus editable via the details view of the widget by adding the following to it:

Copy
<%= scrivito_details_for 'Cropping Focus' do %>
  <%= scrivito_tag :div, widget, :crop_focus %>
<% end %>

To take account of the cropping focus, render the widget in its show view like this:

Copy
<%= scrivito_image_tag widget, :image, {class: 'image-widget'}, transform: {
  height: 50, width: 50, fit: :crop, crop: widget.crop_focus
} %>

You can of course make the dimensions editable as well, or use the code above for a “ThumbnailWidget.”

Accessing original image versions

If a default transformation is in use (see above) you won't be able to access the original version of those images to which this default transformation is applied (because they are too large). You will always get the transformed version when downloading an image from your website or via the Content Browser. This is intentional, of course.

So, what can be done to offer the original version of an image for download or render it in its full size? Simply use the URL the SDK provides for this purpose to render a link or an image tag. In the case of an image widget, use the following to render the original image.

Copy
<%= image_tag widget.image.binary.url %>

For getting at the URL of a binary CMS object in general, use @obj.binary.url. CMS objects are binary objects if they have a blob attribute for accessing the binary data.

Note that original images cannot be edited using the image editor built into Scrivito because the scrivito_tag and scrivito_image_tag helpers cannot handle URLs at this time.

Plain transformations

To perform transformations without using a helper (e.g. as a one-time action in the Rails console), use an API call like this one:

Copy
img_url = widget.image.binary.transform(width: 50, height: 50, fit: :crop).url

This transforms the image and returns the URL of the resulting binary, but it's done synchronously, meaning that it's slow if no such transformation has been executed for the specified image yet.

If you recurringly need to transform images directly, we recommend to use the scrivito_path helper:

Copy
img_url = scrivito_path(widget.image.binary.transform(width: 50, height: 50, fit: :crop))

Using scrivito_path causes the transformations to be executed asynchronously, so they don't have any impact on response times.