Skip to content

Thumbnail Generation

daniel-nelson edited this page Apr 15, 2019 · 25 revisions

Common use cases for thumbnails are pretty easy with Paperclip. You define your preferred sizes in your initial has_attached_file call:

class User < ActiveRecord::Base
  # Paperclip
  has_attached_file :photo,
    :styles => {
      :thumb => "100x100#",
      :small  => "150x150>",
      :medium => "200x200" }

Then you use them like this:

<%= image_tag %>
<%= image_tag %>
<%= image_tag %>

:styles also accepts a lambda, enabling you to access the instance being operated on:

class User < ActiveRecord::Base
  # Paperclip
  has_attached_file :photo,
    :styles => lambda { |a|
                        { :thumb => "100x100#",
                          :user_defined => "#{a.instance.width}x#{a.instance.height}#" }

Resizing options

Default behavior is to resize the image and maintain aspect ratio (i.e. the :medium version of a 300×150 image will be 200×100). Some commonly used options are:

  • trailing #, thumbnail will be centrally cropped, ensuring the requested dimensions.
  • trailing >, thumbnail will only be modified if it is currently larger than the requested dimensions. (e.g the :small thumb for a 120×80 original image will be unchanged)

You can see a complete list of ImageMagick options for more.

Optimizing thumbnails for the web

If you’re creating thumbnails for heavy images, you can greatly reduce sizes for your thumbnails by stripping EXIF data and controlling compression options.

Check out the -strip, -quality and -thumbnail options from ImageMagick’s options. You can expect thumbnails to be 5-10x lighter in size.

Here’s an example on how to apply these flags to your thumbnails:

# Paperclip
has_attached_file :photo,
  :styles => {
    :thumb => "100x100#" },
  :convert_options => {
    :thumb => "-quality 75 -strip" }

Generating/regenerating your thumbnails

Note: regenerating only one of several defined styles as described in some of the examples below will lead to broken paths/urls for all other styles if you have :hash in your paperclip_defaults[:path] and :updated_at in your paperclip_defaults[:hash_data] (and you have by default). Don’t do this unless you really know what you’re doing.

WARNING: regeneration is broken on S3 and will truncate your original images. If you want to reprocess and your images are on S3, use this PR. In any case, back up your images before regenerating (S3 has a copy/paste feature that enables you to copy entire “directories” between buckets, so this is simple).

You can (re)generate your thumbnails en masse with Paperclip’s rake tasks. Using our example class above:

rake paperclip:refresh:thumbnails CLASS=User

or to refresh all of your defined styles in one go (:thumb, :small, :medium from the above example)

rake paperclip:refresh CLASS=User

and to refresh only missing styles:
a list of styles will be defined or updated in a file “/public/system/paperclip_attachments.yml”

WARNING: if something goes wrong, this can delete non-missing style variants from S3. Duplicate S3 images before refreshing missing styles (see above).

rake paperclip:refresh:missing_styles

If you are using the gem required version of paperclip the rake tasks may not be auto-loaded, but you can copy them into your lib/tasks directory if needed.

If you need more manual control or have a lot of thumbnails and only want to process a few, you can use #reprocess! like so:

users_to_reprocess.each do |user|!

Additionally, if you want to only reprocess a single style you may do so like:

users_to_reprocess.each do |user|! :medium

Prevent thumbnail generation for invalid uploads

(Recent versions of Paperclip do this by default without the following code)

If you upload a file that is too large or otherwise doesn’t fit the requirements, paperclip still processes all styles during assignment before the model object is recognized as invalid during #save. This can be a huge waste of time if you’re working with big files and/or many styles.

You can use a before_post_process filter to avoid post processing. For example, if your attribute is named image, and you have a restriction on the file size, the filter could look like this:

before_post_process :check_file_size
def check_file_size
You can’t perform that action at this time.