Class: Image

Inherits:
Attachment show all
Defined in:
lib/yodel/models/core/attachments/image.rb

Instance Attribute Summary

Attributes inherited from Attachment

#field, #mime, #name, #record

Instance Method Summary collapse

Methods inherited from Attachment

#directory_path, #empty?, #exist?, #initialize, #length, #path, #relative_directory_path, #relative_path, #remove_files, #reset_memoised_values, #to_hash

Constructor Details

This class inherits a constructor from Attachment

Instance Method Details

#crop_imageObject



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/yodel/models/core/attachments/image.rb', line 7

def crop_image
  sizes = (@field.options['sizes'] || {}).to_hash.merge('admin_thumb' => '100x100')
  return unless exist?
  
  # determine image dimensions
  # FIXME: uploaded file names with '..' and slashes etc. could be a security issue
  escaped_path = "\"#{path.gsub('"', '\"')}\""
  dimensions = `#{Yodel.config.identify_path} -ping -format "%w %h" #{escaped_path}`
  unless ('0'..'9').include?(dimensions[0])
    raise "Invalid image format or unknown Image Magick error: #{dimensions}"
  else
    iw, ih = dimensions.split.map(&:to_i)
  end
  
  # resize to each custom size, using the given dimensions as a maximum and
  # minimum size - the resulting image is cropped if necessary
  sizes.each do |size_name, size|
    sw, sh = size.split('x').map(&:to_i)
    aspect = sw.to_f / sh.to_f
    w, h = (ih * aspect), (iw / aspect)
    w = [iw, w].min.to_i
    h = [ih, h].min.to_i
    
    command = "#{Yodel.config.convert_path} #{escaped_path} "
    command += "-crop '#{w}x#{h}+#{(iw-w)/2}+#{(ih-h)/2}' "
    command += "-resize '#{sw}x#{sh}' "
    command += "-quality #{Yodel.config.image_quality} "
    command += resized_image_path(size_name, false).to_s
    result = `#{command}`
    raise "Error converting image: #{result}" unless result.empty?
  end
end

#relative_resized_image_path(name, crop_if_required = true) ⇒ Object

TODO: relative path from is quite a complex method; we should optimise the whole path system here somehow



49
50
51
# File 'lib/yodel/models/core/attachments/image.rb', line 49

def relative_resized_image_path(name, crop_if_required=true)
  Pathname.new(resized_image_path(name, crop_if_required)).relative_path_from(Pathname.new(@record.site.attachments_directory))
end

#resized_image_path(size, crop_if_required = true) ⇒ Object

TODO: shouldn’t always be .jpg; have image extension as an option



41
42
43
44
45
46
# File 'lib/yodel/models/core/attachments/image.rb', line 41

def resized_image_path(size, crop_if_required=true)
  return path if size.nil? || size == :original
  sized_path = File.join(@record.site.attachments_directory, relative_directory_path, "#{size}.jpg")
  crop_image unless File.exist?(sized_path) || !crop_if_required
  sized_path
end

#set_file(file) ⇒ Object



2
3
4
5
# File 'lib/yodel/models/core/attachments/image.rb', line 2

def set_file(file)
  super(file)
  crop_image
end

#url(size = :original, crop_if_required = true) ⇒ Object



53
54
55
56
57
58
59
# File 'lib/yodel/models/core/attachments/image.rb', line 53

def url(size=:original, crop_if_required=true)
  if size == :original
    super()
  else
    Pathname.new('/').join(Yodel::ATTACHMENTS_DIRECTORY_NAME, relative_resized_image_path(size, crop_if_required))
  end
end