class Paperclip::Thumbnail

Handles thumbnailing images that are uploaded.

Constants

ANIMATED_FORMATS

List of formats that we need to preserve animation

MULTI_FRAME_FORMATS

Attributes

animated[RW]
auto_orient[RW]
convert_options[RW]
current_geometry[RW]
format[RW]
frame_index[RW]
source_file_options[RW]
target_geometry[RW]
whiny[RW]

Public Class Methods

new(file, options = {}, attachment = nil) click to toggle source

Creates a Thumbnail object set to work on the file given. It will attempt to transform the image into one defined by target_geometry which is a “WxH”-style string. format will be inferred from the file unless specified. Thumbnail creation will raise no errors unless whiny is true (which it is, by default. If convert_options is set, the options will be appended to the convert command upon image conversion

Options include:

+geometry+ - the desired width and height of the thumbnail (required)
+file_geometry_parser+ - an object with a method named +from_file+ that takes an image file and produces its geometry and a +transformation_to+. Defaults to Paperclip::Geometry
+string_geometry_parser+ - an object with a method named +parse+ that takes a string and produces an object with +width+, +height+, and +to_s+ accessors. Defaults to Paperclip::Geometry
+source_file_options+ - flags passed to the +convert+ command that influence how the source file is read
+convert_options+ - flags passed to the +convert+ command that influence how the image is processed
+whiny+ - whether to raise an error when processing fails. Defaults to true
+format+ - the desired filename extension
+animated+ - whether to merge all the layers in the image. Defaults to true
+frame_index+ - the frame index of the source file to render as the thumbnail
Calls superclass method Paperclip::Processor::new
# File lib/paperclip/thumbnail.rb, line 29
def initialize(file, options = {}, attachment = nil)
  super

  geometry             = options[:geometry].to_s
  @crop                = geometry[-1, 1] == "#"
  @target_geometry     = options.fetch(:string_geometry_parser, Geometry).parse(geometry)
  @current_geometry    = options.fetch(:file_geometry_parser, Geometry).from_file(@file)
  @source_file_options = options[:source_file_options]
  @convert_options     = options[:convert_options]
  @whiny               = options.fetch(:whiny, true)
  @format              = options[:format]
  @animated            = options.fetch(:animated, true)
  @auto_orient         = options.fetch(:auto_orient, true)
  @current_geometry.auto_orient if @auto_orient && @current_geometry.respond_to?(:auto_orient)
  @source_file_options = @source_file_options.split(/\s+/) if @source_file_options.respond_to?(:split)
  @convert_options     = @convert_options.split(/\s+/)     if @convert_options.respond_to?(:split)

  @current_format      = File.extname(@file.path)
  @basename            = File.basename(@file.path, @current_format)
  @frame_index         = multi_frame_format? ? options.fetch(:frame_index, 0) : 0
end

Public Instance Methods

convert_options?() click to toggle source

Returns true if the image is meant to make use of additional convert options.

# File lib/paperclip/thumbnail.rb, line 57
def convert_options?
  !@convert_options.nil? && !@convert_options.empty?
end
crop?() click to toggle source

Returns true if the target_geometry is meant to crop.

# File lib/paperclip/thumbnail.rb, line 52
def crop?
  @crop
end
make() click to toggle source

Performs the conversion of the file into a thumbnail. Returns the Tempfile that contains the new image.

# File lib/paperclip/thumbnail.rb, line 63
def make
  src = @file
  filename = [@basename, @format ? ".#{@format}" : ""].join
  dst = TempfileFactory.new.generate(filename)

  begin
    parameters = []
    parameters << source_file_options
    parameters << ":source"
    parameters << transformation_command
    parameters << convert_options
    parameters << ":dest"

    parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")

    frame = animated? ? "" : "[#{@frame_index}]"
    convert(
      parameters,
      source: "#{File.expand_path(src.path)}#{frame}",
      dest: File.expand_path(dst.path)
    )
  rescue Terrapin::ExitStatusError => e
    if @whiny
      message = "There was an error processing the thumbnail for #{@basename}:\n" + e.message
      raise Paperclip::Error, message
    end
  rescue Terrapin::CommandNotFoundError => e
    raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `convert` command. Please install ImageMagick.")
  end

  dst
end
transformation_command() click to toggle source

Returns the command ImageMagick's convert needs to transform the image into the thumbnail.

# File lib/paperclip/thumbnail.rb, line 98
def transformation_command
  scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
  trans = []
  trans << "-coalesce" if animated?
  trans << "-auto-orient" if auto_orient
  trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
  trans << "-crop" << %["#{crop}"] << "+repage" if crop
  trans << '-layers "optimize"' if animated?
  trans
end

Protected Instance Methods

animated?() click to toggle source
# File lib/paperclip/thumbnail.rb, line 115
def animated?
  @animated && (ANIMATED_FORMATS.include?(@format.to_s) || @format.blank?) && identified_as_animated?
end
identified_as_animated?() click to toggle source

Return true if ImageMagick's identify returns an animated format

# File lib/paperclip/thumbnail.rb, line 120
def identified_as_animated?
  if @identified_as_animated.nil?
    @identified_as_animated = ANIMATED_FORMATS.include? identify("-format %m :file", file: "#{@file.path}[0]").to_s.downcase.strip
  end
  @identified_as_animated
rescue Terrapin::ExitStatusError => e
  raise Paperclip::Error, "There was an error running `identify` for #{@basename}" if @whiny
rescue Terrapin::CommandNotFoundError => e
  raise Paperclip::Errors::CommandNotFoundError.new("Could not run the `identify` command. Please install ImageMagick.")
end
multi_frame_format?() click to toggle source
# File lib/paperclip/thumbnail.rb, line 111
def multi_frame_format?
  MULTI_FRAME_FORMATS.include? @current_format
end